Size: a a a

Compiler Development

2020 January 11

YS

Yuriy Syrovetskiy in Compiler Development
MaxGraey
Кстати тут недавно Terry Cavanagh выложил исходники VVVVVV и народ просто в шоке от логики. В совокупности там 300 switch-кейсов, один из которых имеет аж 4000 кейсов =) Так что кто то создает шедевры на ужастной кодовой базе, а кто то делает перфекционный и идеоматичный код на Haskell/Rust/Ocaml/F#/Scala (нужное подчеркнуть) который зачастую никому никогда и не пригодиться) Есть конечно над чем задуматься
и наоборот, кто-то пишет хороший код, который работает, кто-то пишет плохой код, и он не работает. но задумываться — это в любом случае полезно
источник

C

Constantine in Compiler Development
https://t1lang.github.io/

T1 is a programming language which aims at providing better support for constrained environments, especially embedded systems with very little RAM. It should provide the following features:

Embeddable within C-based application with no OS dependency (“bare metal” systems).
Lightweight coroutines with strong guarantees on maximum stack usage.
Type-safe and memory-safe by default.
Predictable memory layout for easier integration with hardware.
Portable output (T1 code may be compiled to plain C).
Very small code footprint through generation of token-threaded code.
Generic metaprogramming support.
Flexible object-oriented support.
источник

C

Constantine in Compiler Development
lack of support for recursion, whole program deductive type analysis, postfix syntax… 🤔
источник

C

Constantine in Compiler Development
A bootstrap interpreter/compiler is being written in C# 😳
источник

M

MaxGraey in Compiler Development
Yuriy Syrovetskiy
и наоборот, кто-то пишет хороший код, который работает, кто-то пишет плохой код, и он не работает. но задумываться — это в любом случае полезно
хороший-плохой код это слишком субъективно и упрощенно, любой код может быть как рабочим так и не рабочим. Можно идуссский код полностью покрыть тестами и он будет рабочим, но будет ли он хорошим? Сопровождаемым? Эффективным?
источник

M

MaxGraey in Compiler Development
Julian =) Coffee
Свитч кейс это конечный автомат
регулярка это тоже конечный автомат. Может будем игровую логику описывать регулярками?) Выйдет намного короче свич-кейсов.
источник

YS

Yuriy Syrovetskiy in Compiler Development
MaxGraey
регулярка это тоже конечный автомат. Может будем игровую логику описывать регулярками?) Выйдет намного короче свич-кейсов.
да, иногда так делают (не в играх)
источник

AT

Alexander Tchitchigin in Compiler Development
MaxGraey
хороший-плохой код это слишком субъективно и упрощенно, любой код может быть как рабочим так и не рабочим. Можно идуссский код полностью покрыть тестами и он будет рабочим, но будет ли он хорошим? Сопровождаемым? Эффективным?
Работоспособность кода - слишком низкая планка. Это как студенты, которые говорят "а почему у меня не 5 - программа же работает?" Интересно, на какую оценку они бы претендавали, если бы код даже не работал?

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

M

MaxGraey in Compiler Development
Alexander Tchitchigin
Работоспособность кода - слишком низкая планка. Это как студенты, которые говорят "а почему у меня не 5 - программа же работает?" Интересно, на какую оценку они бы претендавали, если бы код даже не работал?

Так вот, решение поставленной задачи - это минимальное требование к разрабатываемой программе. Если мы хотим претендавать на Software Engineering, то сам код и его организация (дизайн и архитектура) должны отвечать определённым критериям (обычная фигня: модульность, расширяемость, поддерживаемость, тестируемость и т.п.).
Ну я вот об этом же
источник

AT

Alexander Tchitchigin in Compiler Development
MaxGraey
Ну я вот об этом же
👌
источник

BD

Berkus Decker in Compiler Development
Constantine
https://t1lang.github.io/

T1 is a programming language which aims at providing better support for constrained environments, especially embedded systems with very little RAM. It should provide the following features:

Embeddable within C-based application with no OS dependency (“bare metal” systems).
Lightweight coroutines with strong guarantees on maximum stack usage.
Type-safe and memory-safe by default.
Predictable memory layout for easier integration with hardware.
Portable output (T1 code may be compiled to plain C).
Very small code footprint through generation of token-threaded code.
Generic metaprogramming support.
Flexible object-oriented support.
Should?
источник

E

Eugene in Compiler Development
Dmitry Ponyatov
что-то подумалось, а почему так мало мануалов и статей по самокомпиляции динамических языков?

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

JC

Julian =) Coffee in Compiler Development
Dmitry Ponyatov
ну например JITить куски числомолотильного кода, и генерировать обертки для внешних .dll

по идее такая штука должна была появится в виде отдельного мануальчика из ряда advanced Python где-нибудь в версии 1.2.3 и маленькая библиотечка которая скрывает совсем уж кишки конкретной реализации
Возможно подключить си просто легче
источник

JC

Julian =) Coffee in Compiler Development
Так-то делают и jit, numba, например.
источник

АЗ

Андрей Звёздочка in Compiler Development
Dmitry Ponyatov
что-то подумалось, а почему так мало мануалов и статей по самокомпиляции динамических языков?

ну т.е. например Python или тот же JS дает полный доступ к своей внутрянке (байт-код, информация по наследованию)
почему не стало одной из распространенных практик для юзеров уровня мидла и выше фишка по написанию самокомпиляторов?
Эм, а у js не единственный рантайм. Какой там доступ к байткоду?)
источник

VY

Vasiliy Yorkin in Compiler Development
Не очень понимаю вот этот момент в tiger-book... SL же везде это frame pointer и это первый элемент (первое слово) в списке формальных параметров в стеке. Если кто проходил книгу, то по идее должен понимать о чём я...
источник

VY

Vasiliy Yorkin in Compiler Development
Т.е. стек это
type t = {
 (* Frame unique id (used for equality testing and tracing) *)
 id : int;
 (* Label at which the function's machine code begins *)
 label: Temp.label;
 (* Locations of all the formals *)
 formals: access list;
 (* Number of locals allocated so far *)
 mutable locals: int;
 (* Instructions required to implement the "view shift" *)
 instrs: Instruction.t list;
} [@@deriving show { with_path = false }]

где access это Abstract location of a formal parameter (function argument) or a local variable that may be placed in a frame or in a register:

type access =
 (* Memory location at the specific offset from the frame pointer *)
 | InFrame of int
 (* Register location *)
 | InReg of Temp.t
[@@deriving show { with_path = false }]

(* Creates a new location for a formal parameter or
  a local variable, given its index and [escape] flag *)
let mk_access i = function
 | true -> InFrame ((i + 1) * (-word_size)) (* Escapes -- alloc in frame *)
 | false -> InReg (Temp.mk ()) (* Doesn't escape -- use [Temp.t] (register) *)

(* Makes a new stack frame *)
let mk ~label ~formals =
 let id = next_id () in
 let formals = List.mapi formals ~f:mk_access in
 let locals = 0 in
 (* Don't know yet what instructions we need,
    so just leave it empty for now *)
 let instrs = [] in
 { id; label; formals; locals; instrs }

Соответственно, когда я транслирую у меня есть такая абстракция как level:

type level = {
 parent: level option;
 frame: Frame.t
} [@@deriving show { with_path = false }]

let new_level ~parent ~label ~formals =
 (* The first "formal" is static link (SL) which
    is a frame pointer (FP) that we'll use for
    calculating the variable address, when the
    variable is accessed from a nested level/frame *)
 let static_link = true in
 let formals = static_link :: formals in
 let frame = Frame.mk ~label ~formals in
 { parent; frame }

Т.е. SL всегда первый в списке formals в структуре данных стек-фрейма. Что значит "VARIOUS static link offsets" на стр. 156?



И если я хочу реализовать ф-цию, которая вернёт IR-выражение, для получения адреса нужного фрейма для того, чтобы получить адрес переменной, которая определена во внешнем фрейме\скоупе , типа follow_sl

(** We need to use static links to access variables
   declared at an outer level of static scope.

   For example, to access some variable [x] which is declared
   somewhere outside of the current level/scope/frame the
   generated IR code should look like:

   Mem(BinOp(Const k_n, Plus, Mem(BinOp(Const k_n-1, Plus,
   ...
   Mem(BinOp(Const k_1, Plus, Temp fp))))))

   where k_1,...,k_n-1 are the various SL offsets in nested functions,
   and k_n is the offset of our variable [x] in its own frame.

   This function follows the given number of static links (SL) between
   the current [Translate.level] of use and the [Translate.level] of definition. *)
val follow : int -> Ir.expr

То вот это вот выражение, представленное формулой

Mem(k_n + Mem(K_n-1 + ... + Mem(K_1 + FP)))

вырождается в

Mem(Mem(...Mem(FP)))
, где number of Mem's = of frames between the inner and outer "levels"

Потому что по факту K_n = K_n-1 = ... K_1 = 0, или я чего-то не понимаю...

В общем, я думаю, что я правильно всё понял.
На самом деле мне нужно просто использовать ф-цию exp, которую мы ранее по книги определили
(* We need the [addr] here to access different frames.
  The address of the frame is the same as the
  current frame pointer only when accessing the variable
  from its own level. When accessing the variable [access] from an
  inner-nested function, the frame address must be calculated
  using static links, and the result of this calculation will be
  the [addr] argument to our [expr] function (Page 156) *)

let expr access ~addr =
 let open Ir in
 match access with
 | InFrame k -> Mem addr @+ Const k
 | InReg t -> Temp t

Mem addr @+ Const k ==> Mem (Const 0) @+ addr ==> Mem addr
где addr это всегда Frame 0

типа того
https://github.com/vyorkin/tiger/blob/master/chapter7/lib/sl.ml#L22
источник

E

EgorBo in Compiler Development
источник

AK

Andrei Kurosh in Compiler Development
MaxGraey
Кстати тут недавно Terry Cavanagh выложил исходники VVVVVV и народ просто в шоке от логики. В совокупности там 300 switch-кейсов, один из которых имеет аж 4000 кейсов =) Так что кто то создает шедевры на ужастной кодовой базе, а кто то делает перфекционный и идеоматичный код на Haskell/Rust/Ocaml/F#/Scala (нужное подчеркнуть) который зачастую никому никогда и не пригодиться) Есть конечно над чем задуматься
Там написано, что это порт оригинальной флеш-версии. Может быть, эти адовые свичи нагенерила какая-то утилита для портирования?
источник

VY

Vasiliy Yorkin in Compiler Development
И все if then else тоже %)
Да нет, похоже на рукописный код (хотя я не уверен на 100%, что это так, коментарии могли тоже быть сгенерированы)
источник