LINUX.ORG.RU

История изменений

Исправление quasimoto, (текущая версия) :

подумай, как его реализовать например в системе кодов x86, и всё поймёшь

А как реализовать в системе кодов x86

(a + b) * (c + d)

? Очевидно

r0 = a
r0 += b
r1 = c
r1 += d
r0 *= r1

А теперь паттерн-матчинг:

data Term a =  a :+ a | a :* a | L a

t x = case x of
  (L a :+ L b) :* (L c :+ L d) -> (a + b) * (c + d)
  ...

и (наиболее тупой) результат компиляции:

t2 x =
  if isProd x
  then let l1 = getProdLeft x
           r1 = getProdRight x
       in if isSum l1
          then let l2 = getSumLeft l1
                   r2 = getSumRight l1
               in if isSum r1
                  then let l3 = getSumLeft r1
                           r3 = getSumRight r1
                       in if isLit l2
                          then let l2' = getLit l2
                               in if isLit r2
                                  then let r2' = getLit r2
                                       in if isLit l3
                                          then let l3' = getLit l3
                                               in if isLit r3
                                                  then let r3' = getLit r3
                                                       in (l2' + r2') * (l3' + r3')
                                                  else ...
                                          else ...
                                  else ...
                          else ...
                  else ...
          else ...
  else ...

дальше нужны тайптеги у типов-сумм, typeof-ы для них и акцессоры. Это можно оптимизировать минимизируя branching, но в целом всё довольно просто и в духе zero cost (Страуструп одобряет, вместе с разработчиками Rust и Cyclone). Необходимость в тайптегах подобна необходимости в vtbl у виртуальных функций, сам паттерн-матчинг даёт лёгкость расширения наборов функций для фиксированных (закрытых) типов данных (по отношению к expression problem, виртуальные функции ООП наоборот — лёгкость расширения данных предоставляющих фиксированные наборы интерфейсных функций).

Исходная версия quasimoto, :

подумай, как его реализовать например в системе кодов x86, и всё поймёшь

А как реализовать в системе кодов x86

(a + b) * (c + d)

? Очевидно

r0 = a
r0 += b
r1 = c
r1 += d
r0 *= r2

А теперь паттерн-матчинг:

data Term a =  a :+ a | a :* a | L a

t x = case x of
  (L a :+ L b) :* (L c :+ L d) -> (a + b) * (c + d)
  ...

и (наиболее тупой) результат компиляции:

t2 x =
  if isProd x
  then let l1 = getProdLeft x
           r1 = getProdRight x
       in if isSum l1
          then let l2 = getSumLeft l1
                   r2 = getSumRight l1
               in if isSum r1
                  then let l3 = getSumLeft r1
                           r3 = getSumRight r1
                       in if isLit l2
                          then let l2' = getLit l2
                               in if isLit r2
                                  then let r2' = getLit r2
                                       in if isLit l3
                                          then let l3' = getLit l3
                                               in if isLit r3
                                                  then let r3' = getLit r3
                                                       in (l2' + r2') * (l3' + r3')
                                                  else ...
                                          else ...
                                  else ...
                          else ...
                  else ...
          else ...
  else ...

дальше нужны тайптеги у типов-сумм, typeof-ы для них и акцессоры. Это можно оптимизировать минимизируя branching, но в целом всё довольно просто и в духе zero cost (Страуструп одобряет, вместе с разработчиками Rust и Cyclone). Необходимость в тайптегах подобна необходимости в vtbl у виртуальных функций, сам паттерн-матчинг даёт лёгкость расширения наборов функций для фиксированных (закрытых) типов данных (по отношению к expression problem, виртуальные функции ООП наоборот — лёгкость расширения данных предоставляющих фиксированные наборы интерфейсных функций).