Login

Subversion Repositories NedoOS

Rev

Rev 344 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

для файлов с переменными можно сгенерить include в каждом
но надо знать модель памяти (вдруг надо разделить команды и данные!)

Now the _isaddr flag is set if another address was used in a calculation, and reset in multiplications (see _OPMUL in asmj.c). Maybe I must add rule: addr-addr is a number. For this, tempvalue and pushvalue stack must be typed.


add(mul(px,px),add(mul(py,py),mul(pz,pz))) - ГЛЮК (первый add получает первый параметр уже затёртым), и при глубинных вызовах тоже

глюк в выражениях с тайпкастом:
struct zzz{
  BYTE ba;
  LONG lb;
  STRUCT zzz* pcc;
}

TYPEDEF STRUCT zzz* tpzzz

CONST STRUCT zzz zuzu={
  0x03,
  5L,
  &zuzu
}
VAR STRUCT zzz* pzz1
VAR tpzzz pzzz

CONST UINT zzz_nnn = 0;
VAR LONG l0 = &zuzu->lb;
VAR LONG l1 = (STRUCT zzz*)((UINT)&zuzu+zzz_nnn)->lb
выдаёт
;PUSHNUM zuzu ;Line=24
;PUSHNUM zzz.lb ;Line=24
;PUSHCONST zuzu ;Line=24
        LD HL,zuzu
;OPERATION + ;Line=24
;PUSHCONST zzz.lb ;Line=24
        LD DE,zzz.lb
        ADD HL,DE
;PEEK ;Line=24
        LD E,[HL]
        INC HL
        LD D,[HL]
        INC HL
        LD A,[HL]
        INC HL
        LD H,[HL]
        LD L,A
;POPVAR l0 ;Line=24
        LD [l0],DE
        LD [l0+2],HL
;PUSHNUM zuzu ;Line=25
;OPERATION cast 31>1 ;Line=25
;PUSHNUM zzz_nnn ;Line=25
;PUSHCONST zuzu ;Line=25
        LD HL,zuzu
;OPERATION + ;Line=25
;PUSHCONST zzz_nnn ;Line=25
        LD DE,zzz_nnn
        ADD HL,DE
;OPERATION cast 1>31 ;Line=25
;PUSHNUM UINT.lb ;Line=25
;OPERATION + ;Line=25
;PUSHCONST UINT.lb ;Line=25
        LD DE,UINT.lb ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        ADD HL,DE
;PEEK ;Line=25
        LD E,[HL]
        INC HL
        LD D,[HL]
        INC HL
        LD A,[HL]
        INC HL
        LD H,[HL]
        LD L,A
;POPVAR l1 ;Line=27

let variable=l1 type=4, but expr type=47;_test.c line=27
operation popvar bad type=47;_test.c line=27

TODO ещё поддержать VAR LONG l1 = (&zuzu+zzz_nnn)->lb (но в Си так нельзя, он домножит zzz_nnn на размер)


сделать вложенные скобки в дефайнах, иначе нельзя типизированные -(a/b)

#include "name.h"
должен выдавать:
include "name.dec"
incobj "name.bin","name.rel" или просто incobj "name"
это может быть любое место исходника (в стартапе инклюды в конце)
что если заголовочный файл включает другой заголовочный файл? ничего страшного, как будто подряд?

как использовать один и тот же заголовочный файл для объявлений и использования? в gcc так нельзя?
extern!=export (в си нет export)

как передавать нумерацию модулей для обращений в объектнике?
можно ли относительный номер перенумеровать в глобальный? (один и тот же модуль может быть включен в разные!!!)
номер можно назначать по порядку компиляции (даже если перекомпилировать неизменённый не надо)
надо перекомпилировать неизменённый модуль, если он использует изменённый модуль!!! (это потому что он привязывается к смещениям в декларациях используемого модуля)
даже если привязываться не к смещениям, а к номерам символов, то вставка функции потребует перекомпилировать все модули, которые используют его
можно от первого изменившегося перекомпилировать все последующие модули
ещё надо перекомпилировать всё при изменении структуры связей модулей

если это не сделать, то в линкере надо работать с символьными метками, то есть линкер не может стать лоадером (нужна память под метки)

какой символ сделать для деклараций типа metka=<symbol><номермодуля>+<смещение>?
или другой формат деклараций?

ассемблерный файл должен знать свой номер модуля, чтобы правильно выгружать декларации!
не страшно, если у ассемблера будет тот же список файлов, что у компилятора?
или список файлов компилятора ни на что не влияет?




не следует объединять .ast и .var в один файл (т.к. их надо компилировать в разные пространства)
а инициализированные переменные - ещё одно пространство? сейчас явных нет, но есть константные массивы и структуры










ускорение сборки:
- убрать токенизатор из главной цепочки, недоланг должен генерировать токенизированный асм без перелопачивания выражений, а недоасм должен уметь вычислять выражения нормально. nedodel и movedisk можно будет тоже убрать из главной сборки
- асмоверсии работы с метками пусть используют страницы. не делить компилятор на 2 части
- сделать однопроходный асм (с пост-метками)?
- вклеить однопроходный асм прямо в недоланг?
- убрать ещё какие-нибудь специфические процедуры в асмомодули (например, rdtword, genautonum)
- добавить передачу параметров в регистрах
? добавить REGISTER
? токенизировать недоланг (ключевые слова и двойные символы)
? генерировать обж прямо из недоланга (с патчами)(тогда нельзя асмовставки и асмопроцедуры - только асмомодули), сделать специальный линкер или лоадер






построение проекта:
в ассемблер попадает больше файлов, чем в компилятор, т.к. добавляются ещё стандартные процедуры умножения-деления и файлы с переменными
или в ассемблер попадёт всего два файла - склеенный код (с приклеиванием стандартных процедур) и склеенные переменные, или только один склеенный код


если просто вклеить токенизатор в компилятор, то он будет слишком жирным (особенно по меткам)
можно убрать инлайн ассемблер и заставлять инклюдить токенизированные ассемблерные файлы
тогда компилятор просто будет выводить токенизированный асм вместо текста

reader будет общий у компилятора и токенизатора (и поддерживает комменты)
тогда reader должен писать коммент в нетокенизированный ассемблерный текст и в токенизированный одинаково
или нетокенизированный ассемблерный текст не существует
тогда комментарии/ошибки тоже должны об этом знать! токенизировать комментарии/ошибки на уровне emitter?
(компилятор может не выводить ошибки в ferr, а выводить прямо в асм)








типность можно убрать в _istype (обнулять при старте и после тайпкаста)

раньше не было зарезервированных слов
сейчас зарезервированы слова:
- default (можно разрезервировать, но тогда 1. нельзя получить указатель на метку (в gcc особая команда &&labelname?), [2. пользовательские метки пересекутся с автометками (но можно добавить не одну точку, а две)])
- TRUE, FALSE (если будет include, то можно определить, но сам тип BOOL лучше не определять - он нужен в if, while, repeat)
- имена базовых типов - а они не соответствуют зарезервированным сишным именам!
(ассемблерные команды вроде как не зарезервированы, т.к. имя метки проверяется в начале строки)


чтобы заполнить константную структуру, надо где-то взять список полей
или каждое поле будет выделяться по размеру написанного там значения (чревато багами)
зато можно объединить с массивом
но сейчас нельзя определить ширину типа по tword - она определяется по типу массива


todo:
в структуре поле типа массив
переделать &arr[] в &(arr[]) для упрощения?


;для такого (call...=...define) не хватает двух проходов, и ошибка не пишется
closewrite=fclosewrite
closewrite.A.=fclosewrite.A.
        EXPORT closewrite
        EXPORT closewrite.A.
...
EXPORT PROC fclosewrite(PBYTE file)
{
  fclose(file);
}


в асме добавить LIMIT addr, при достижении этого адреса выводить ошибку limit

todo проверить знаковое сравнение (вроде в рейтрейсе работало?)

todo проверить в токенизаторе, ставится ли LF перед ошибкой в начале строки (при отладке Thumb вылезло)

в Си помечаются не int, а uint (1U)

в Си помечается не export, а локальность (const - для функций, по крайней мере)

указатели FAR, NEAR, HUGE - где взять образцы исходников в таком стиле?
в C++ особый указатель на функцию-член класса, хранит также this

в Си limits.h содержит INT_MAX, CHAR_BIT итп


a >> n, a << n, p + n (в Си) - не алгебраические операции, т.к. их операнды разного типа
-a (в NedoLang), p - p (в Си), сравнения - не алгебраические операции, т.к. их результат другого типа


15 nesting levels for #included files limit
#include nesting
Commentary
This limit makes no distinction between system headers and developer-written header files. However, an
implementation is required to support its own system headers whose contents are defined by the standard. If
a particular implementation chooses to use nested #includes, then it is responsible for ensuring that these
do not prevent a translator from meeting its obligations with regard to this limit.
Use of nested #includes requires that the source file containing each of the #include directive be kept
open, while the included file is processed. Supporting 15 nesting levels invariably requires keeping at least
17 (the top-level source file and the file holding the generated code also need to be counted) files open
simultaneously. Using the fsetpos library function to record the current file position, at the point the fsetpos
function
#include occurs, and closing the current file before opening the nested include is possible; however, your
author has never heard of an implementation that uses it.
...
C90
8 nesting levels for #included files
cbook1_0b

C90
257 case labels for a switch statement (excluding those for any nested switch statements)
The intent here was to support switch statements that included 256 unsigned character values plus EOF 1737 switch
statement
(usually implemented as -1).
cbook1_0b


баг:
////////////
CONST PBYTE tasks;

PROC importtasks(PBYTE tasks)
{
}

PROC main()
{
  importtasks(tasks);
}
///////////
nolbl main.tasks
надо таблицу адресов коротких локальных меток


TODO в асме локальные метки процедур .label (компилятся как title.label)
новая метка заголовка определяется в команде PROC
(можно по умолчанию, но это замедлит)

TODO CY вместо C

TODO проверить DB "string",'c',0x00


для ООП нужно (даже без is-a, только с has-a):

- как узнать размер объекта, даже если он точно имеет нужный интерфейс?
???
отдельный интерфейс size или даже copyable? или даже listable?
или все объекты списка одного размера (содержат только интерфейсы), а особая часть каждого класса будет в отдельном блоке памяти? (а как тогда клонировать объекты? через интерфейс copyable?)

- как обратиться к нужному интерфейсу, если он в объекте может располагаться в разных местах? (а он может - интерфейсов может быть разное число). из списка мы получаем какой-то сферический объект, в котором надо только найти интерфейсы, а интерфейсы уже настроены в этом экземпляре на нужную реализацию (конструктором). как найти в объекте нужные интерфейсы по имени?
пусть даже нельзя будет добавлять интерфейсы в объекты одного списка - у всех объектов списка будет один список интерфейсов. тогда надо, чтобы все интерфейсы (или ссылки на них) были включены в начало структуры.
как это контролировать языком? можно сделать один интерфейс "распиновка", включающий все нужные интерфейсы? типа
obj1->visualobject->viewable->View(obj1->visualobject->viewable)
или
(VisualObject)obj1->viewable->View(obj1) - как это на Недоланге???
или
CALL (VisualObject)obj1->viewable->view(obj1) - так нельзя вернуть значение!
или
result = Viewable_View(obj1->visualobject->viewable) //Viewable - пространство имён
как короче???
а кроме этого в obj1 будет только obj1->data с произвольным структурным типом, чтобы не считать размер?
как контролировать, что мы настроили все интерфейсы на нужную реализацию в конструкторе? (если они по указателю, то для этого надо ещё их создать! или не создавать, если конструктор с параметром-объектом) (С++ не контролирует, но вроде может сам вызвать все деструкторы, к тому же сам назначает виртуальные функции)

- как вызвать конструктор и деструктор? их указатели тоже должны быть в фиксированном месте структуры, но не могут быть в obj1->data, т.к. data создаётся в конструкторе. они не могут быть и в obj1->visualobject по той же причине. но могут быть в obj1.visualobject (если вложенные структуры), но тогда все visualobject будут одинаковые, что мы не хотим
вызывать конструктор как простую функцию, а не как метод класса?

- как передать параметры в конструктор, если он по указателю?
вызывать конструктор как простую функцию, а не как метод класса?
типа
typedef <функция, возвращающая object*> Func;

STRUCT IVisualObject{
  IViewable* viewable; //там Proc View
  ICopyable* copyable; //там size и Func Copy
  IListable* listable; //там Func Prev и Func Next???
};

STRUCT VisualObject{ //образец подкласса visualobject, используемый для хранения в списках и т.п.
  IVisualObject* visualobject;
};

STRUCT Button{
  IVisualObject* visualobject;
  ... //data for Button
};
VAR [STRUCT] Button* btOK = CreateButton(10,10,100,100,"OK",&OnClickOK);
//можно тип VisualObject* вместо Button*
...
destroyButton(btOK);
надо вызывать из конструктора объекта конструктор "распиновки" с нужными параметрами - так можно проверить, что не пропустили ни одной инициализации интерфейсов (хотя пока Недоланг не проверяет число параметров). типа так:

FUNC Button* createButton(...) //можно тип VisualObject* вместо Button*
{
VAR [STRUCT] Button* obj;
  obj = newStruct(+sizeof(Button));
  //obj->size = +sizeof(Button);
  obj->VisualObject = createVisualObject(..., obj/**для copyable*/, +sizeof(Button)/**для copyable*/, &ButtonView/**для viewable*/);
  obj->... = ... //data for Button
RETURN obj;
}

- как передавать параметры в виртуальные методы?
в Недоланге нет передачи по стеку
читать из именованных параметров прообраза виртуальной функции? они недоступны из языка! а как их передать в прообраз, при этом вызвать виртуальную функцию? сам прообраз будет вызывать?

Клонирование визуального объекта (в том числе клонирование данных по указателям??? в Qt так нельзя ради рефлексии и иерархии экземпляров):
obj2 = obj1->visualobject->copyable->Copy(obj1)???
obj должен быть приведён к типу VisualObject*!!! сразу всё хранить как VisualObject*, а не Button*?


FUNC UINT Viewable_View(Viewable* viewable, UINT par1)
{
  _par1 = par1;
  CALL viewable->View(); //читает _par1, возвращает _res
RETURN _res;
}
как бы сделать в Недоланге, чтобы вызывать функцию с результатом по указателю?
в сишнике ад: ((<тип>(*)(void))(pfunc))()
+call(pfunc) нельзя, если возвращаем указатель

как в сишнике определить тип PROC? (это когда уберём слово PROC в процедурах)

избавиться сразу от звёздочек в типах за счёт дополнительного typedef?

как избавиться от вставки ->visualobject?
можно наследовать структуру от "распиновки" IVisualObject (для этого надо будет скопировать все поля IVisualObject в нашу структуру), тогда "распиновка" будет лежать в начале
можно тупо:
STRUCT VisualObject{ //образец подкласса visualobject, используемый для хранения в списках и т.п.
#include "visualobject.h" //начинка структуры "распиновки" без обёртки
};
STRUCT Button{
#include "visualobject.h" //начинка структуры "распиновки" без обёртки
  ... //data for Button
};
только Недоланг не умеет инклюды внутри структуры!!!
и не умеет макросы дефайнами!!!
???
используем везде процедуры VisualObject_...(object), где объект имеет тип "образца наследника интерфейса", тогда мы не увидим таких вставок ->visualobject нигде ни в реализации Button, ни в использовании

проблема с распиновкой:
у каждого визуального компонента своя распиновка!
или можно добавить методы и данные вне распиновки? по распиновке обращается ось, а по отдельным методам - форма


STRUCT Button{
  IVisualObject* visualobject;
  //data for visible
  BOOL visible;
  UINT left;
  UINT top;
  UINT width;
  UINT height;
  //data for listable
  List* head;
  Button* prev; //TODO как listable будет в них искать свои поля и свой интерфейс?
  Button* next;
  //data for Button
  PBYTE onclick; //todo PROC
  PCHAR text; //todo STRING
};

PROC VisualObject_View([STRUCT] VisualObject* object) //этот параметр - не интерфейс, а образец подкласса
{
  _this = object;
  CALL object->visualobject->viewable->view;
}

FUNC [STRUCT] VisualObject* VisualObject_Copy([STRUCT] VisualObject* object) //этот параметр - не интерфейс, а образец подкласса
{
  _this = object;
  CALL object->visualobject->copyable->copy;
}

PROC Button_View()
{
  ... _this->left, _this->top, _this->width, _this->height ...
  ... _this->text
}

FUNC [STRUCT] VisualObject* Button_Copy()
{ //кнопка ничего не создаёт, поэтому копируется легко
//TODO вклиниться в цепочку prev,next
RETURN ([STRUCT] VisualObject*)getmem_copy(+sizeof(Button), _this);
}

//статическое создание
//TODO нужны ли ...able? они сами по себе ничего не делают и не защищают
//viewable и clickable явно относятся к visualobject
//listable можно выделить, если там будут смещения до prev,next, а функции GetPrev, GetNext, GetHead, GetSize, IsEmpty, Add, Remove всегда одинаковые
//copyable опасно, потому что семантика неясна (копировать ли вложенные объекты? по идее не попировать, и интерфейсы хранить как подструктуры, а не по ссылке!). чтобы класть в контейнер, достаточно наследовать интерфейс listable и т.п. можно даже неколько раз, если данные прошиты многими ссылками
CONST [STRUCT] IViewable buttoniviewable{
  &Button_View
};
CONST [STRUCT] ICopyable buttoncopyable{
  &Button_Copy //должна знать +sizeof(Button) и что лишнего создавать (а надо ли когда-нибудь создавать лишнее?)
};
CONST [STRUCT] IListable buttonlistable{
  &Button_Prev, //должна знать, где лежит prev (тут нельзя, разве что смещение - т.к. для всех кнопок) //но смещение нельзя получить в константное выражение???
  &Button_Next //должна знать, где лежит next (тут нельзя, разве что смещение - т.к. для всех кнопок) //но смещение нельзя получить в константное выражение???
};
CONST [STRUCT] IClickable buttonclickable{
  &Button_Click
};
CONST [STRUCT] IVisualObject buttonvisualobject{
  &buttonviewable, //там Proc View
  &buttoncopyable, //там Func Copy (она знает +sizeof(Button)) //а нужна ли?
  &buttonlistable, //там Func Prev и Func Next //или смещения до head,prev,next???
  &buttonclickable
};
CONST [STRUCT] Button btOK{
  &buttonvisualobject, //нельзя распиновку кнопки (она одинаковая для всех кнопок) включать в саму общую структуру
  &onClickOK, //onclick
  &listhead, //head (там size, ссылка на реальный head и ссылка на родителя произвольного типа?)
  &btOK, //prev
  &btOK, //next
  10, //left
  10, //top
  100, //width
  100, //height
  "OK" //text
};

//динамическое создание
VAR [STRUCT] VisualObject* btOK = Button_Create(10,10,100,100,"OK",&vbutton,&onClickOK);
//TODO вручную привязать prev, next, т.к. нельзя привязать их все друг к другу в конструкторе (next указывает на будущий объект!)
...
//VisualObject_View(btOK->ivisualobject, btOK); //во всех нужных интерфейсах уже стоят указатели на реализации, а в них нужны указатели на поля Button!
//CALL btOK->visualobject->viewable->view(btOK); //не надо знать, что это кнопка, это просто образец подкласса visualobject
VisualObject_View(btOK);
...
//CALL btOK->visualobject->clickable->click(btOK);
VisualObject_Click(btOK);
...
Button_Destroy(btOK);


можно передавать параметры через байты перед заголовками функций
(нерекурсивно, нереентерабельно, не для ПЗУ, несовместимо с iofast и др.)