Форум программистов, компьютерный форум CyberForum.ru

Пишем свой интерпретатор языка BASIC - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Меню и список http://www.cyberforum.ru/cpp-beginners/thread41194.html
Здравствуйте форумчане. Помоги пожалуйста в следующем вопросе: У меня есть 2связный список, написано меню. Но в моменте когда написано make a list и delete custom необходимо чтобы выводились: Введите элемент и номер. вот сам код: #ifndef __list_h #define __list_h #include <iostream>
C++ Здравствуйте! Не могу поместить class в один файл с программой. file.hpp #include "Cat.hpp" // здесь классы "2)" Cat::Cat(int initialAge) { itsAge = initialAge; } Cat::~Cat() { http://www.cyberforum.ru/cpp-beginners/thread41186.html
Массивы строк C++
Привет всем! Задан массив строк. Как узнать который символ встечаетса найбольшое количество раз в етом массиве?
C++ вывод на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер
Please, help me!!! Вот текст программы, которая выводит на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер только квадратов. Проблема в том, что необходимо исправить код, чтоб фигуры не исчезали за экран (т.е. 640х460) и были компактным набором, т.е. двигались неменяя своего положения относительно друг друга и стукаясь об стенку экрана меняли свое...
C++ Округление дробного числа до целого в большую сторону. http://www.cyberforum.ru/cpp-beginners/thread41139.html
Доброго дня. Я новичок в программирование на Visual C++. Проблема такая программа должна считать кол-во месяцев, если числа целые то программа шла дальше, если дробное то (например 3.33333) программа не округляет это число (в большую сторону) до 4. Перелопатил тонны литературы, но пропустил или не нашёл этого, большая просьба написать функцию которая могла бы это делать, или способ какой.
C++ Код из Delphi в C++ Нужно написать курсовую на C++. Сам я в программировании плохо шарю (не программист). Попросил у народу помощи, помогли. Но решение на Delphi: {$APPTYPE CONSOLE} type byteset=set of byte; var d:array of longint; procedure c; var a,b,i:longint; подробнее

Показать сообщение отдельно
Evg
Эксперт CАвтор FAQ
17632 / 5856 / 376
Регистрация: 30.03.2009
Сообщений: 16,146
Записей в блоге: 26
20.12.2009, 11:35
Как интерпретировать процедуры через промежуточное представление - я вот так с ходу и не скажу. Проблема именно в рекурсивных вызовах. Видимо надо уже над переменными строить надствройку в виде некоторой страницы (которая по сути пул памяти, хранилище). Т.е. при создании переменной ты ещё и указываешь и страницу, в которой эта переменная живёт. Страница для глобальных переменных будет одна. Для локалов и формальных параметров каждой процедуры заводится своя страница и все переменные ссылаются на эту страницу. При наличии рекурсивного вызова процедуры всю страницу можно куда-нибудь в сторону скопировать. Таким образом с точки зрения нашего представления вроде бы остаётся всё как есть: внутреннее представление каждой переменной всегда находится в одном и том же месте памяти интерпретатора. Но это - некий технический бубен, потому как наше представление было рассчитано на случай без функций.

Как вариант можно строить наше же представление. С незначительными отличиями:
- вместо одной цепочки операторов будет несколько цепочек (на каждую функцию отдельная цепочка)
- каким-то образом нужно отличать глобальные переменные от локальной переменной функции. Способов миллион от страниц, про которые говорил выше, до списков переменных, привязанных к каждой процедуре
Оба отличия с технической точки зрения НЕ являются сложными и НЕ являются бубнами/подпорками/костылями. Получится так называемое представление высокого уровня, которое попросту отражает исходник программы в удобный вид для обработки в интерпретаторе (ну и плюс отсеиваем пользовательские ошибки).

Представление верхнего уровня будет использоваться только для хранения "образа программы". Далее нужно построить ещё одно промежуточное представление, которое удобно для интерпретирования. Это будет представление низкого уровня, которое внутри себя будет читывать динамические стеки и прочую лабуду, возникающую при исполнении. Компиляторы, как правило строятся на двух промежуточных представлениях с тем же назначением: высокоуровневое представление, чтобы иметь образ программы, и низкоуровневое, чтобы с него генерировать код.

Высокоуровневое представление оперирует понятиями "объект" ("переменная"). Низкоуровневое - понятиями "память" и "регистр".

Для исходника

PureBasic
1
A = B + C
на высоком уровне мы имеем операцию типа (пишу несколько условно, чтобы отобразить тот факт, что у нас ето всё в одной операции (statement), который по сути имеет некую древовидную конструкцию.

Код
ASSIGN (VAR A, PLUS (VAR B, VAR C))
на низком уровне это разложится в более примитивные операции типа:

Код
OBJPTR A -> r1   <-- запись адреса переменной в некий регистр r1
OBJPTR B -> r2
OBJPTR C -> r3
LOAD   [r2] -> r4    <-- загрузка значения из адреса, записанного в r2, в регистр r4
LOAD   [r3] -> r5
ADD    r4, r5 -> r6  <-- сложение значений на регистрах r4 и r5 и запись результата в регистр r6
STORE  r6 -> [r1]    <-- запись значения и регистра r6 по адресу, записанному в регистре r1
Для реальной машины и компилятора в каждом случае надо знать, с каким форматом данных мы работаем (т.е. это int32, int64, float32, ...). От формата данных зависит конкретная аппаратная операция для чтения и арифметики. В случае интерпретатора можно не заморачиваться и считать, что наши "регистры" содержат Value, а потому разбор конкретного типа данных происходит в момент арифметической операции над Value (что у нас уже реализовано)

Адрес глобальных переменных в run-time всегда будет одним и тем же. Адреса локальных переменных будут плавать (в зависимости от глубины стека). В этом случае понадобятся страницы (фрэймы) памяти. Все глобальные переменные будут распределены в одну страницу для глобалов. При входе (на исполнении) в каждую процедуру будет заводиться страница для локалов процедуры и туда помещаться все локалы. Адрес локальной переменной будет вычисляться на основании адреса текущей страницы локалов.

Да, всё это на первый взгляд слишком непонятно. Непонятно так же, как это будет выглядеть технически. Но для начала надо хотя бы в общем виде понять концепцию двух представлений. Причём пока писал, уже понял, что низкоуровневое представление можно значительно сократить. А так же построить его на базе высокоуровневого, т.к. на первый взгляд раличие будет только при работе с переменными. Но это мысли "на потом", для начала понять концепцию.

Прежде, чем это делать, тебе всё-таки нужно навести порядок во внутренностях интерпретатора, потому что закопаешься. И ещё сделать нормальную печать промежуточного представления, чтоб "глазами" можно было увидеть всё, что в нём есть и как оно друг с другом связано (как это смотреть в моей версии, я вроде бы уже писал). В gcc эти печати даже не стали прятать от пользователя (хотя во всех коммерческих компиляторах в пользовательских версиях) она отключена. Запусти "gcc t.c -da" и ты увидишь файлы "gcc t.c.*", в которых расписано представление после каждого прохода или оптимизации. Без подобной НОРМАЛЬНОЙ печати компилятор реализовать просто невозможно
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru