2 pontos por GN⁺ 2023-07-18 | 1 comentários | Compartilhar no WhatsApp
  • Forth começou como um pequeno interpretador criado por Chuck Moore para reduzir o longo fluxo de compilação e cartões perfurados, e acabou evoluindo para um sistema que absorveu editor, sistema operacional e compilador
  • A notação pós-fixada (RPN), a pilha de dados e as palavras (dictionary) não eram uma sintaxe exótica, mas um projeto voltado a reduzir desperdício e trabalho repetitivo em hardware cheio de limitações
  • O núcleo do Forth está em uma estrutura bootstrapável na qual até elementos como :, ;, IF, comentários e variáveis podem ser definidos e redefinidos dentro da própria linguagem
  • Implementações como JonesForth, nasmjf, PlanckForth e sectorforth mostram que o Forth pode começar com dezenas ou centenas de bytes, ou com um pequeno número de primitivas, e se expandir para interpretador, compilador, assembler e DSL
  • Os casos de espaçonaves, Open Firmware, Jupiter Ace, Canon Cat, Harris RTX2010 e GreenArrays mostram que o Forth tem forte afinidade com desenvolvimento interativo, código pequeno, proximidade com o hardware e computação de baixo consumo

Do mito da Usenet ao ponto de partida para explorar Forth

  • Dave Gauer organizou uma jornada pessoal de descoberta do Forth e de sua inserção na história da computação, e esta página é uma adaptação de slides de uma apresentação curta
  • Nos anos 1990, os grupos comp.* da Usenet, especialmente comp.lang.*, eram um lugar importante para aprender e discutir programação
    • O primeiro anúncio do Linux por Linus Torvalds também é citado como um caso publicado em 1991 no comp.os.minix
    • No fim dos anos 1990, Perl teve grande peso na Web inicial como linguagem para páginas dinâmicas e processamento de formulários via CGI
  • Lendas encontradas na era da Usenet, como linguagens da família Lisp, o combinador Y, The Little Schemer e The Story of Mel, levaram à curiosidade sobre Forth
  • No começo, o Forth apareceu como uma linguagem “tão flexível que seria possível mudar o valor de um inteiro”, e Chuck Moore ficou na memória como um “mad wizard” capaz de escrever qualquer programa com poucas telas de código
  • A série do blog de James Hague, programming in the twenty-first century, foi o impulso final para explorar Forth

RPN e pilha são apenas o ponto de partida

  • A primeira impressão do Forth é a notação pós-fixada ou Reverse Polish Notation (RPN)
    • Diferentemente da notação infixa comum 3 + 4, o Forth coloca o operador depois dos operandos, como em 3 4 +
    • O exemplo em Forth 3 4 * 5 6 * + . imprime 42
    • Em dc, o mesmo cálculo é expresso como 3 4 * 5 6 * + p
  • A RPN permite calcular expressões aninhadas na ordem desejada sem parênteses
    • 3 4 * produz 12, 5 6 * produz 30, e o + final gera 42
    • Em Forth, . retira um valor da pilha e o imprime
  • A calculadora HP-35 é um caso histórico importante para a popularização da RPN fora da ciência da computação
    • No início dos anos 1970, a HP já tinha calculadoras de mesa poderosas, e a HP-35 é apresentada como o caso que colocou essa capacidade de cálculo em uma calculadora de “bolso da camisa”
    • As calculadoras da HP eram famosas pela sintaxe RPN, que era eficiente, mas podia parecer um tanto enigmática para quem vinha de fora
  • A segunda característica é a pilha de dados
    • Operações como PUSH, POP, SWAP e DUP também são palavras do Forth
    • Ao inserir números, eles vão para a pilha, e os operadores retiram valores dela, fazem o cálculo e colocam o resultado de volta
  • A pilha reduz a necessidade de dar nomes a valores intermediários
    • Em muitas imperative languages, são necessários nomes temporários como result2 e matched_part3
    • Essa forma de trabalhar sem nomes também é chamada de programação implícita, tácita ou point-free
    • Entender Forth apenas por RPN e pilha é insuficiente, mas isso ainda faz sentido como ponto de partida para compreender suas origens históricas

Programação concatenativa, Joy e a diferença em relação ao Forth

  • Ao explorar o Forth, logo se encontra o conceito de programação concatenativa
    • Um exemplo applicative é eat(bake(prove(mix(ingredients))))
    • Um exemplo concatenative é ingredients mix prove bake eat
    • As funções são listadas em sequência, e o valor de cada etapa é passado implicitamente para a próxima
  • Joy é um caso representativo de concatenative language
    • Manfred von Thun se inspirou na ACM Turing Award lecture de 1977 de John Backus, “Can Programming Be Liberated from the von Neumann Style?”
    • Em Joy, toda função recebe uma pilha como entrada e retorna uma pilha como saída
    • O programa é uma lista de funções lida da esquerda para a direita
  • As quotations e combinators de Joy mostram uma forma de computação sem variáveis
    • Em JavaScript, [1, 2, 3, 4].map(n => n + 1) produz [2,3,4,5]
    • Em Joy, o mesmo resultado é obtido com [1 2 3 4] [1 +] map
    • Em Joy, [] é um mecanismo de quotation que pode conter não só dados, mas também programas
  • Combinator é tratado como uma função de ordem superior que recebe funções como entrada
    • map() é um exemplo de abstração do código repetitivo de percorrer uma lista
    • Os combinators I, K e S, além do cálculo SKI, aparecem como construções que explicam computação universal
    • S e K já bastam para formar um sistema completo para computação universal
  • O Forth também pode criar funções de ordem superior com execution token e a palavra EXECUTE
    • FOO EXECUTE executa a palavra retornada pela palavra FOO
    • É possível definir palavras combinatórias como MAP, FOLD e REDUCE
  • Forth e Joy têm uma sintaxe superficialmente parecida, mas interpretam expressões de formas diferentes
    • Em Forth, 2 3 + é lido como “empurre 2 e 3 para a pilha e some”
    • Em Joy, é lido como “a composição das funções 2, 3 e + é equivalente à função 5”
    • O Forth está mais próximo de uma linguagem que cresceu na interação com o hardware do que de uma linguagem guiada principalmente por princípios abstratos de computação concatenativa

O caminho que levou Chuck Moore a criar o Forth

  • Em 1958, Chuck Moore usava Fortran e o IBM 704 durante seu período no Smithsonian Astrophysical Observatory e no MIT
    • Em Forth, the Early years, Moore diz: “Compiling took 30 minutes...you got one shot per day”
    • O IBM 704 era um computador valvulado que ocupava uma sala inteira, e aparece junto a uma citação de que quebrava, em média, a cada cerca de 8 horas
  • Para reduzir a recompilação, Moore criou um interpretador simples que lia cartões que controlavam o programa
    • Era possível montar equações diferentes para vários satélites sem precisar recompilar
    • O formato de entrada livre era mais confiável para humanos escreverem do que as colunas formatadas do Fortran
    • Esse sistema acabou se tornando a origem do que mais tarde seria chamado de Forth
  • Em 1961, em Stanford, Moore usou o Burroughs B5500 e escreveu uma aplicação matemática chamada CURVE
    • O CURVE incluía um interpretador mais sofisticado, data stack e operadores de control flow
    • As funcionalidades correspondiam, em linhas gerais, a palavras do Forth como IF ELSE DUP DROP SWAP + - *
    • Com a adição de uma parameter stack e da capacidade de definir novos procedures, surgiu uma estrutura mais próxima do Forth
  • Por volta de 1965, com o surgimento de ambientes de teletype, paper tape, timesharing e terminais interativos, o Forth se tornou mais interativo
    • Foram adicionadas palavras como KEY, EMIT, CR, SPACE, DIGIT
    • Essas palavras transformaram o sistema de Moore em um editor de programas, permitindo ao usuário editar programas de dentro do próprio programa
  • Em 1968, na Mohasco, Moore trabalhou com o IBM 1130 e deu o nome “FORTH” ao sistema
    • O IBM 1130 tinha configuração de 16 bits e 8 KB de RAM, e os nomes de arquivos eram limitados a 5 caracteres
    • O sistema de “fourth generation” de Moore virou FORTH por causa desse limite de 5 caracteres
    • Nessa época, foram adicionados a return call stack e o dicionário de palavras
  • O dicionário nomeado de palavras do Forth funciona como sua principal abstração
    • : DOUBLE DUP + ;
    • : QUAD DOUBLE DOUBLE ;
    • Sem a return stack, após executar DOUBLE não seria possível voltar para a posição restante de QUAD

NRAO, portabilidade e indirect threaded code

  • No começo dos anos 1970, Moore escreveu software de controle de computadores para radiotelescópios no National Radio Astronomy Observatory
    • O NRAO tinha uma política de usar Fortran em minicomputadores, mas Moore recebeu permissão para usar Forth com base em seus sucessos anteriores
    • Em spectral-line observing, era possível exibir os spectra que estavam sendo coletados e ajustar line-shapes por mínimos quadrados
    • Esse trabalho avançou o estado da arte em online data reduction, e astrônomos o usaram para descobrir e mapear moléculas interestelares
  • Elizabeth “Bess” Rather adotou o Forth e escreveu o primeiro manual da linguagem em 1972
    • Depois, cofundou a FORTH, Inc com Chuck Moore
    • Até se aposentar em 2006, continuou sendo uma das principais especialistas e promotoras da linguagem Forth
  • O Forth foi portado para várias máquinas, como IBM 360/50, Honeywell 316, Honeywell DDP-116 e DEC PDP-11
    • A implementação de Forth para o H316 foi programada no próprio computador e usada para criar outros Forths, sendo considerada a primeira implementação completa e autônoma
    • O PDP-11 é um minicomputador importante ligado à história do Unix e da linguagem de programação C
  • Por trás da possibilidade de portar o Forth para várias máquinas está o indirect threaded code
    • Aqui, threaded code não tem relação com concorrência nem com programação multithread
    • Threaded code armazena uma lista de endereços de sub-rotinas em vez de instruções de chamada de sub-rotina
    • Para executar essa lista de endereços, é necessário um interpretador de código
  • O indirect threaded code armazena uma lista de endereços que apontam para endereços que apontam para o código, e não endereços que apontam diretamente para o código
    • Graças a essa segunda indireção, é possível ter um inner interpreter separado para cada tipo diferente de sub-rotina
    • No Forth, o outer interpreter é a parte com que o usuário interage no terminal, e o inner interpreter executa o restante das palavras
  • Nesse ponto, o Forth já tinha ido muito além de um simples interpretador de comandos, expandindo-se para linguagem interativa, editor, sistema operacional e método de armazenamento e execução de código
    • Suas características passam a incluir postfix notation, orientação a pilha, estilo concatenativo, interpretação, alta adaptabilidade à arquitetura da máquina e tamanho extremamente compacto
    • O Forth não foi uma linguagem projetada de uma vez em 1958, mas o resultado de algo que Moore fez crescer conforme suas necessidades e o novo hardware

Para entender Forth, é preciso implementar um Forth

  • No conselho “To understand Forth, you have to implement a Forth”, a palavra importante é a Forth
    • Na visão de Chuck Moore, um sistema Forth funciona melhor quando é custom-tailored para o sistema e a tarefa
  • Antes de lidar com o código-fonte do JonesForth, o autor escreveu Assembly Nights para aprender fundamentos de assembly e da ABI do Linux
    • O JonesForth usa código em assembly i386 escrito para o montador GNU GAS
    • É exclusivo para 32 bits e usa diretamente a ABI de system calls do Linux
    • O autor passou cerca de um ano portando o JonesForth para uma cópia que funciona com o montador NASM, e esse porte é o nasmjf
  • No processo de portar o nasmjf, ele aprendeu como funciona um Forth tradicional de indirect threading
    • O jonesforth.S do JonesForth é um único arquivo com a parte em assembly, e Richard W.M. Jones guia o fluxo do interpretador com ASCII art e explicações
    • O autor escreveu vários diagramas em ASCII art no código-fonte do nasmjf para organizar seu próprio entendimento
  • A macro NEXT é o fluxo central que faz a execução passar para a próxima palavra após a palavra atual
%macro NEXT 0
    lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
    jmp [eax] ; Jump to whatever code we're now pointing at.
%endmacro
  • lodsd move um double word da memória para eax e atualiza o ponteiro para indicar a próxima posição
  • jmp [eax] transfere a execução para o local atualmente apontado, tornando-se o inner interpreter dessa sub-rotina
  • No Forth tradicional, existem basicamente code words e colon words
    • Code words são primitivas escritas em machine code
    • Colon words são palavras comuns escritas na linguagem Forth e montadas pelo compilador :
    • Colon words terminam com EXIT, e EXIT processa a return stack antes de continuar o fluxo com NEXT
  • O Forth é uma estrutura em que pedaços muito pequenos trabalham juntos para formar um sistema em execução
    • Em baixo nível, isso traz flexibilidade e simplicidade, mas em níveis mais altos a facilidade de entendimento pode ser sacrificada

Palavra de código, palavra de dois-pontos e compilador funcionam sobre o mesmo interpretador

  • SWAP, DUP, DROP mostram o quão diretamente os primitivos de Forth podem ser implementados em código de máquina
DEFCODE "SWAP",SWAP,0
    pop eax
    pop ebx
    push eax
    push ebx
NEXT
DEFCODE "DUP",DUP,0
    mov eax, [esp]
    push eax
NEXT
DEFCODE "DROP",DROP,0
    pop eax
NEXT
  • O JonesForth usa a pilha de call/return do i386 como a pilha de parâmetros do Forth, então implementa as operações de pilha com pop e push nativos
  • O nasmjf tem 130 palavras de código, e a maioria existe por eficiência
    • há um mínimo teórico para a quantidade de palavras em código de máquina necessária para um sistema Forth bootstrappable
    • reduzir demais a quantidade de primitivos pode tornar o restante do código Forth ineficiente e distorcido
    • A 3-INSTRUCTION FORTH FOR EMBEDDED SYSTEMS WORK, de Frank Sergeant, trata de um Forth de 3 instruções que precisa de apenas 66 bytes no Motorola MC68HC11
    • sectorforth é um Forth x86 de 16 bits que cabe em um setor de boot de 512 bytes
  • uma palavra de dois-pontos é a forma de criar uma nova palavra pela composição de palavras existentes
: SDD SWAP DROP DUP ;
  • SDD produz o mesmo efeito que chamar SWAP DROP DUP em sequência
  • do ponto de vista de código threaded indireto, uma palavra de dois-pontos é compilada como os endereços do interpretador interno dessas três palavras de código
  • : e ; parecem sintaxe, mas na prática são palavras de Forth
    • : pega o nome da nova palavra e ativa o modo de compilação
    • ; finaliza a nova entrada no dicionário e desativa o modo de compilação
    • o usuário pode substituir o próprio : por sua própria definição para estender ou alterar o Forth
    • a única sintaxe de Forth é tratada como whitespace entre tokens de entrada
  • em Forth, compilar é colocar na memória endereços de palavras ou literais e código de push
    • no modo normal, a palavra é executada imediatamente
    • no modo de compilação, o endereço da palavra é armazenado na memória
    • o mesmo interpretador faz tanto a execução quanto a compilação do código
  • até estruturas de controle como IF...THEN podem ser implementadas no próprio Forth
: IF IMMEDIATE ' 0BRANCH , HERE @ 0 , ;

: THEN IMMEDIATE DUP HERE @ SWAP - SWAP ! ;
  • O fato de até um elemento tão fundamental quanto IF ser definido dentro da própria linguagem é a principal base do título “A linguagem de programação que escreve a si mesma”
  • comentários aninhados em ( ... ) também são implementados em Forth em jonesforth.f
    • até comentários são implementados dentro da linguagem, e o usuário pode redefini-los ou adicionar seu próprio estilo de comentário
    • esse exemplo reforça que Forth quase não tem sintaxe nativa

Dicionário e redefinição criam extensibilidade

  • O dicionário de Forth tradicionalmente usa uma lista encadeada, e a correspondência de palavras começa pela entrada mais recente
    • a definição mais recente de uma palavra com o mesmo nome encobre a definição anterior
    • qualquer palavra pode ser redefinida, inclusive palavras definidas inicialmente em assembly
    • palavras já compiladas armazenam endereços, não nomes, então continuam apontando para o endereço da palavra anterior à redefinição
  • é possível estender uma palavra chamando a palavra anterior com o mesmo nome a partir da nova definição
    • ao criar uma palavra recursiva, : oculta da lista do dicionário, ou marca como inativa, a palavra que está sendo compilada no momento
    • para chamar a si mesma dentro da palavra atual, é preciso usar RECURSE
  • o exemplo da variável de maçãs, adaptado de Thinking Forth, mostra a flexibilidade do Forth
    • VARIABLE APPLES cria a palavra APPLES, que ao ser chamada coloca um endereço de memória na pilha
    • 20 APPLES ! armazena 20 nesse endereço
    • APPLES ? busca o valor e o exibe
    • Thinking Forth (PDF) é disponibilizado gratuitamente
  • mesmo que seja preciso rastrear separadamente maçãs vermelhas e maçãs verdes, o código existente que usa APPLES não precisa ser alterado
VARIABLE COLOR

VARIABLE REDS
: RED REDS COLOR ! ;

VARIABLE GREENS
: GREEN GREENS COLOR ! ;

: APPLES COLOR @ ;
  • a nova APPLES também é uma palavra que coloca um endereço na pilha, então a forma de usar APPLES ! e APPLES ? continua a mesma
  • apenas o endereço passa a alternar entre REDS e GREENS conforme a cor de maçã ativa
  • do ponto de vista de linguagens convencionais, parece que uma variável virou uma função, mas em Forth não há mudança no conceito em nível de linguagem, porque tanto variáveis quanto funções são palavras
  • até tokens que parecem números podem ser redefinidos como palavras do dicionário
: 4 12 ;
  • ao executar ." The value of 4 is " 4 . CR, a saída será The value of 4 is 12

Meow5 e Forth como “o caminho de menor resistência”

  • o nasmjf, um port de JonesForth para NASM, não foi um esforço para reproduzir o processo de Moore, mas um exercício mais próximo de observar em detalhe uma “cópia-mestre” do produto final
  • depois disso, o autor conduziu um experimento extremo de programação concatenativa chamado Meow5
    • Meow5 é um experimento de sempre concatenar e inlinar todo o código
    • ele é concatenativo porque usa o conceito de pilha de parâmetros, como o Forth
    • foi um experimento mental levado ao limite: e se, em vez de armazenar endereços de chamadas de função, o sistema armazenasse cópias completas das funções?
  • o núcleo do Meow5 é tornar todas as palavras 100% inline
    • a ideia partiu de inline expansion, uma otimização comum para evitar o overhead de chamar funções pequenas
    • chamar um primitivo de uma instrução como DROP passando por vários saltos parecia desperdício
  • Meow5 terminou como um “pequeno fracasso divertido”
    • o inline de código de máquina em si funcionou bem, e o executável ELF gerado também funcionou como esperado
    • o problema eram os dados de string: ou era preciso copiar a string toda vez, ou rastrear de forma complexa quais palavras usavam strings
    • a palavra INLINE do Forth, que oferece inline seletivo, foi avaliada como uma abordagem melhor
  • a sintaxe de strings também confirmou novamente o conselho de Moore
    • em Forth, usa-se a palavra ", então é preciso haver espaço, como em " Hello World."
    • o Meow5 adotou um estilo de aspas mais natural, na forma "Hello World.", e sequências de escape como \n e \"
    • por causa dessa escolha, foi necessário tratar " como exceção em vários pontos do tokenizer e do interpretador, reduzindo a pureza e a simplicidade
  • quando se começa a seguir o caminho do Forth, o restante parece se encadear como se “escrevesse a si mesmo”
    • Forth é bootstrapping, metaprogramação, e pode ser sistema operacional e IDE/editor
    • isso leva à afirmação de que, ao criar o interpretador mais simples possível para uma arquitetura de CPU totalmente nova, você pode acabar usando algo parecido com Forth

Implementações pequenas de Forth e usos reais

  • Forth pode definir mais Forth dentro do próprio Forth, e muitas implementações de Forth também incluem assembler
    • No fim do JonesForth há um stub de assembler que funciona dentro de Forth
    • ;CODE atualiza o header para que o codeword aponte para código montado, e não para DOCOL
  • PlanckForth é um Forth binário escrito à mão com menos de 1 KB
    • Um binário ELF completo e uma implementação funcional de Forth cabem em menos de 1 KB
    • bootstrap.fs começa com operadores iniciais difíceis de entender e, algumas centenas de linhas depois, vira um Forth fácil de ler
  • Exemplos de implementações pequenas mostram a compressibilidade extrema de Forth
    • SmithForth é um Forth em código de máquina escrito à mão por David Smith, apresentado como um sistema Forth de 1.000 bytes e 1.000 linhas
    • sectorforth é um Forth de boot sector com 512 bytes
  • Forth é usado em usinas elétricas, robótica, sistemas de rastreamento de mísseis, automação industrial, linguagens embutidas em videogames, bancos de dados, contabilidade, processadores de texto, gráficos, sistemas de cálculo, o boot loader Open Firmware e vários processadores e microcontroladores
  • Open Firmware é um caso importante surgido da engenharia da Sun Microsystems
    • Por ser baseado em uma linguagem de programação interativa, permite testar e fazer o bring-up de novo hardware com eficiência
    • No caso do Space Shuttle ESN, Open Firmware é tratado como uma ferramenta capaz de depurar hardware, software, drivers em plug-in e até o próprio firmware
  • Jupiter Ace foi um computador doméstico britânico de 1982 cujo sistema operacional era Forth
    • O OS e a routine library cabiam em uma ROM de 8 KB
    • Há uma citação de 1982 dizendo que o Forth embutido era “10 vezes mais rápido” que o BASIC interpretado e exigia menos da metade da memória
  • O Canon Cat tinha um sistema operacional em Forth em 1987 e colocava OS, suíte de escritório e ambiente de programação em 256 KB de ROM
    • Era um produto que implementava em hardware e software a interface centrada no teclado e a filosofia de design de Jef Raskin
    • O procedimento para entrar na interface de Forth não parece ser o fluxo de uso principal, mas, sabendo como fazer, é possível com algumas teclas

Software espacial e Forth

  • Um dos usos mais interessantes de Forth é na exploração espacial
    • Naves espaciais têm custo alto e são difíceis ou impossíveis de reparar, então a confiabilidade do software é importante
    • A lista de projetos da NASA que usaram Forth é longa; o link original desapareceu, mas há cópias no Wayback Machine e no forth.com
  • O Space Shuttle Small Payload Accommodations Interface Module (SPAIM) é um exemplo de uso de Forth
    • A equipe de desenvolvimento escrevia rotinas em Forth no PC, fazia o download e depois testava interativamente
    • Há uma citação dizendo que o flight software do SPAIM funcionou sem problemas durante a missão STS-45 do Shuttle
    • O sistema Forth do SPAIM suportava multitasking, cada task tinha sua própria stack, e uma watchdog task monitorava o estado das stacks
  • O Space Shuttle Robot Arm Simulator é um caso em que um programador desenvolveu um equipamento complexo em 5 semanas
    • Ele precisava receber comandos de joystick de 3 eixos para controlar um braço de 50 pés de comprimento, com 6 juntas e 6 sistemas de coordenadas
    • Há uma citação dizendo que o system tinha 14 process separados
    • Há uma citação de que os testes de simulação foram tão completos que, após a instalação no local, o algoritmo de executive control não foi alterado
  • O Shuttle Mission Design and Operations System (SMDOS) era um software de controle em solo da JPL
    • Durante a missão SIR-B, várias falhas de hardware foram tratadas no local com modificações no software
    • Problemas na antena e uma mudança de órbita exigiram uma nova estratégia de coleta de dados, e o SMDOS foi usado para exibir planos adequados às novas condições
    • Muito dado foi perdido, mas 20% dos dados foram recuperados por meio do método girar-capturar-girar-transmitir
  • O Harris RTX2010 era hardware Forth usado em muitas aplicações espaciais
    • Execução direta de Forth
    • 2 hardware stacks com profundidade de 256 words
    • Clock de 8 MHz e baixa latência
    • Características radiation-hardened
  • Rosetta e Philae são apresentados como a primeira missão a enviar uma nave para orbitar um cometa e pousar um módulo em sua superfície
    • O Ion and Electron Sensor da Rosetta usa o Harris RTX2010
    • O lander Philae usava 2 RTX2010 no CDMS e mais 2 para controle do ADS
    • A Rosetta viajou de 2004 a 2014 até encontrar o 67P/Churyumov-Gerasimenko
    • O 67P tem 4 km de largura e orbita o Sol a cada seis anos e meio
  • O Philae sofreu quiques na superfície em baixa gravidade por falha dos arpões e do thruster de pouso, mas foi robusto o bastante para cumprir “80%” de sua missão científica
  • Também aparece o caso de um patch de código do magnetômetro da Galileo em 1993
    • O magnetômetro tinha RCA1802, 2 KB de RAM e 2 KB de ROM, e era programado em Forth em um sistema de desenvolvimento baseado no Apple II
    • Um byte defeituoso de memória surgiu no meio do código do equipamento, e foi preciso criar um patch para evitar usar aquele byte
    • O autor da citação escreveu do zero, em Lisp, um ambiente de desenvolvimento Forth e um simulador de hardware para o equipamento para gerar o patch, e isso levou menos de 3 meses em meio período

Forth está mais para uma ideia e uma linhagem do que para uma única implementação

  • Forth está mais próximo de uma ideia com conceitos compartilhados e linhagem do que de uma única implementação representativa
  • Um dos motivos pelos quais é difícil aprender Forth é que não existe uma única implementação que represente de forma exclusiva o nome “Forth”
    • Algumas formas iniciais de Forth são anteriores ao próprio nome “Forth”
    • O padrão de Forth continua nos documentos do ANS Forth, com menções ao Forth 2012 Standard e ao comitê Forth200x
  • As implementações de Forth compartilham conceitos e words em comum, mas Forths especializados por objetivo têm seu próprio vocabulário específico
  • Chuck Moore fundou a Forth, Inc em 1973 e desde então tem portado Forth para vários sistemas, além de continuar criando novos sistemas
  • colorForth é um ambiente posterior de Chuck Moore
    • As cores no código-fonte substituem parte da pontuação do Forth padrão para determinar como os words são processados
    • O texto afirma que as cores simplificam a semântica de Forth, aumentam a velocidade de compilação e também ajudam com a visão fraca de Moore
    • colorForth inclui seu próprio sistema operacional de 63 KB
  • Moore acredita que o software fica mais complexo à medida que funcionalidades continuam sendo adicionadas, até ninguém mais conseguir mudar nada por medo de consequências não intencionais
    • Isso leva à defesa de que o necessário é um programador dedicado, que devote a carreira a uma única aplicação, reescrevendo-a repetidamente até torná-la perfeita

Afinidade mecânica, chips Forth, GreenArrays

  • Chuck Moore se opõe à complexidade do software desde os anos 1950, e aparecem citações em que ele vê sistemas operacionais como Windows, UNIX e DOS como incompreensíveis ou desnecessários
  • O autor explica a filosofia de Moore como Mechanical Sympathy
    • Essa expressão veio de uma citação do piloto de Formula One Jackie Stewart e, no contexto de software, foi usada por Martin Thompson em Why Mechanical Sympathy?
    • Forth tende a ser popular entre “pessoas de hardware”, como engenheiros elétricos e projetistas de sistemas embarcados
  • O verdadeiro interesse de Chuck Moore parece estar no projeto de processadores
    • O Harris RTX2000 e o RTX2010 são apresentados basicamente como chips de Moore
    • Moore projetou hardware a partir do gate array Novix N400 de 1983, e um projeto aprimorado foi vendido à Harris, tornando-se o chip RTX
  • Moore projetou processadores com seu próprio software de VLSI OKAD, escrito em 500 linhas de Forth
    • VLSI Design Tools (OKAD) explica que 500 linhas de colorForth fornecem tudo o que é necessário para projetar chips
    • O OKAD é um conjunto de ferramentas que inclui tecnologia de portas lógicas, layout de circuitos, simulation de comportamento elétrico e exportação em GDSII
  • O Novix NC4000 é um mecanismo de processamento ultrarrápido projetado para executar diretamente instruções Forth de alto nível
    • Ele obtém desempenho eliminando assembly language convencional e microcode interno
    • A architecture de pilha dupla reduz bastante o overhead de implementação de subrotinas
  • Os chips da GreenArrays são apresentados em torno da palestra de Moore de 2013, “Programming a 144-computer chip to minimize power”
    • Um único chip contém 144 computadores assíncronos
    • Um core ocioso consome 100 nW, um core ativo consome 4 mW, executa a 666 Mips e depois volta ao estado ocioso
    • Quando todos os computadores operam na velocidade máxima, o consumo é de 550 mW, cerca de 0,5 W
  • O documento GreenArrays Architecture enfatiza “NO CLOCKS”
    • Explica-se que a geração e distribuição de clock em computadores comuns consomem muita energia mesmo em espera, sem fazer trabalho algum
    • A GreenArrays é apresentada não como uma Multi-Core CPU, mas como um Multi-Computer System

Simplicidade, eficiência e o futuro da computação de baixo consumo

  • O autor vê software e hardware seguindo continuamente na direção de empilhar mais camadas de complexidade
    • A computação em grandes datacenters é percebida como barata ou gratuita porque é paga indiretamente por verba de publicidade
    • Explica-se que o que realmente se paga é com a atenção e os dados pessoais dos usuários
  • Argumenta-se que não há motivo para continuar usando software cada vez mais ineficiente e mal construído, junto com exigências de hardware cada vez mais severas
  • Linguagens semelhantes a Forth podem ter um futuro forte nas seguintes áreas
    • computadores pequenos e onipresentes
    • energia solar
    • VMs fortemente restritas
  • O Dennard scaling praticamente parou por volta de 2006
    • A relação em que transistors menores permitiam velocidades mais altas e tensões mais baixas chegou a um platô em cerca de 4GHz por causa de fuga de corrente e calor
    • The Free Lunch Is Over, de Herb Sutter, é apresentado como um texto sobre a mudança na forma de aumentar o desempenho de CPUs para hyper-threading e multicore
  • Sutter defende que é preciso redesenhar aplicações para concorrência ou escrever código mais eficiente e menos desperdiçador
    • Ele diz que a otimização de desempenho não está se tornando menos importante, mas mais importante
  • Hoje é possível comprar, por poucas moedas, um microcontroller muito mais poderoso que o IBM 704 e escrever sobre ele um poderoso system Forth
    • Um microcontroller pode funcionar com bateria tipo moeda ou com um pequeno painel solar
    • Segue-se a ideia de que nunca houve uma época mais impressionante para a computação em pequena escala
  • Para entender Forth, é preciso considerar a diferença entre “simple” e “easy”
    • Simple Made Easy, de Rich Hickey, é apresentado como a palestra que lhe deu vocabulário para expressar essa distinção
    • Forth não é fácil e talvez nem sempre seja agradável, mas certamente é uma linguagem simples
  • Growing a Language, de Guy Steele, é uma palestra que mostra como uma linguagem é construída a partir de primitivas
    • A citação do Lisp, de que quando novas palavras definidas pelo usuário parecem primitivas e as primitivas também parecem palavras definidas pelo usuário, surge uma linguagem maior sem emendas, é aplicada ao Forth também
  • A recomendação final é criar a linguagem de programação perfeita para você mesmo

1 comentários

 
GN⁺ 2023-07-18
Comentários do Hacker News
  • Assim que conheci Forth, pensei que precisava tentar fazer um eu mesmo, então criei o MiniForth em apenas uma semana há 2 anos
    Era voltado para o Blue Pill e o Arduino original, mas desenvolvi com um compilador cruzado para poder testar no host
    Fiquei tão envolvido que mal via a hora de chegar em casa para mexer nisso todo dia depois do trabalho, e terminei em cinco noites de semana e um dia de fim de semana; fazer um Forth foi tão divertido assim
    Recomendo muito esse processo, e a única experiência parecida de revelação que tive foi quando conheci macros de Lisp pela primeira vez (https://www.thanassis.space/score4.html#lisp)
    • Concordo. Na aula de arquitetura de computadores do primeiro ano, tive que fazer um projeto final de tema livre para o LC-3, e como eu já tinha brincado um pouco com Forth no mod RedPower 2 do Minecraft, achei que seria divertido implementar
      Isso consumiu quase todo o meu tempo livre naquele semestre, e em certo dia só fui olhar o relógio quando o sol já estava nascendo e percebi que tinha virado a noite
      Nunca usei Forth de forma prática na vida real, mas a experiência de construir um do zero foi algo que dá para descrever quase como uma experiência religiosa
      Parecia a destilação pura do que Fred Brooks dizia sobre programação: o programador, como um poeta, trabalha só um pouco afastado do material bruto do pensamento puro, construindo castelos no ar apenas com a imaginação, e programas são magia real em que, se você disser o encantamento certo, algo que antes não existia ganha vida na tela
    • Concordo totalmente. Há muito tempo, fiz um compilador de Forth em ZX81 BASIC
      Algo que levava 19 segundos para imprimir 1000 números na tela passou a terminar instantaneamente
      Também tirei uma grande lição disso: olhei para o código de máquina gerado e pensei que estava perfeito e que não dava para melhorar, mas voltei no dia seguinte e consegui torná-lo muito mais rápido
  • Você pode se perguntar: “Como assim ele escreve a si próprio? Isso não quer dizer só que dá para escrever funções?”
    Em certa medida, sim, mas Forth vai além porque permite definir novas palavras e fazê-las virar parte da própria linguagem
    Essas palavras podem ser usadas como operações embutidas e até mudar a forma como a linguagem funciona
    Como é uma linguagem extensível, também dá para definir novas estruturas de controle ou criar palavras que mudem a sintaxe, e esse tipo de flexibilidade é incomum em outras linguagens
    Nesse sentido, Forth pode ser visto como uma linguagem que “escreve a si própria”, porque permite ao programador personalizar e expandir a linguagem em um nível bem fundamental
    Isso também é parecido com o sistema de macros de Lisp: assim como macros de Lisp permitem criar novas estruturas sintáticas e linguagens específicas de domínio por meio de transformações em tempo de compilação, as palavras de Forth também permitem expandir a sintaxe e a funcionalidade
    • É legal, mas em quase 40 anos trabalhando como programador profissional, o problema nunca foi a sintaxe, e sim a semântica
      Pode haver situações, como multiplicação de matrizes, em que escrever A = B + C * D; seja melhor do que especificar manualmente qual função chamar, mas nunca encontrei esse tipo de problema na prática
      Fico pensando se me falta imaginação, se isso só é útil em certos domínios e eu nunca estive neles, se a sintaxe do Forth é pobre demais e precisa ser expandida para ficar utilizável, ou se as pessoas só gostam de personalizar a linguagem como quem tunando um carro
      Não entendo muito bem por que as pessoas realmente se interessam por isso
  • Um dos projetos em Forth mais interessantes hoje é o Dusk OS, um sistema operacional de 32 bits escrito em Forth que inclui seu próprio compilador C, e vários ports também estão em andamento
    https://duskos.org/
    • Não conheço bem o DuskOS em si, mas historicamente é verdade que Forth era “seu próprio sistema operacional”, embora, comparado ao que um leitor moderno imagina como sistema operacional, fosse algo bem rudimentar
      Claro, o fato de rodar em 8 KB de RAM limita o que se pode esperar, mas apesar de oferecer funcionalidades primitivas, historicamente quase não havia drivers nem a maioria dos conceitos de abstração
      O código era carregado a partir do fonte, então era lento, e o linking era mais parecido com carregar blocos na ordem certa; para carregar um novo programa, primeiro era preciso remover o programa atual
      Não sei se isso era muito melhor que o CP/M, que muitas vezes reiniciava a máquina a frio ao encerrar um programa, mas pelo menos o CP/M separava BIOS e BDOS
    • Eu tinha deixado isso passar. Acabei de ler “Beyond the Collapse” e senti que, com minha experiência em Lisp, APL/J e C, é difícil chegar perto da simplicidade do Forth no nível de sistema operacional
      Com certeza vou dar uma olhada antes do próximo fim de semana
  • Minhas primeiras linguagens de programação foram assembly x86 e Forth. Meu pai era obcecado por Forth, e foi com ele que aprendi a programar
    Na adolescência, fiz vários sistemas Forth x86 para DOS, e o último deles acabou virando uma implementação ANS compatível bem polida chamada “Third”: https://github.com/benhoyt/third
    É impressionante poder ter um compilador Forth totalmente bootstrapado, incluindo assembler, em apenas alguns milhares de linhas de código
    Há pouco tempo, transcrevi um artigo antigo que escrevi em coautoria para a revista Forth Dimensions
    As ideias do Forth ainda são boas, mas a manipulação de pilha logo fica cansativa e se torna muito difícil de ler
    Dá para ver isso nos exemplos de código em https://benhoyt.com/writings/forth-lookup-tables/, especialmente em Search-Table. Dar nomes já é difícil, mas não dar nomes parece ainda pior
    • Talvez a manipulação de pilha fique cansativa porque nem você nem eu somos o Chuck Moore
      O código dele em geral tem pouquíssima bagunça de pilha. Ex.: http://www.merlintec.com/download/color.html
    • Dei uma olhada rápida no código-fonte do Third e achei interessante
      No bootstrap ele chama kernel.com; fiquei curioso sobre como o kernel.com foi compilado
  • Palestra relacionada do Chuck Moore: “Programming a 144 Computer Chip to Minimize Power” (2013)

https://www.youtube.com/watch?v=0PclgBd6_Zs
Dizem que é assim que o Forth roda computadores de ultrabaixo consumo: a GreenArrays está entregando chips assíncronos de 144 núcleos, e a energia necessária é de apenas 7 pJ/inst
Núcleos ociosos não consomem energia (100 nW), e núcleos ativos executam rapidamente com 4 mW (666 Mips) antes de ficar ociosos aguardando comunicação

  • “Sempre achei que tamanho e velocidade só importavam para amadores. Mas, no contexto moderno, há apenas três parâmetros que importam: potência, potência, potência
    --Chuck Moore
    https://youtu.be/0PclgBd6_Zs?t=389
  • Fico realmente me perguntando se esse tipo de estrutura topológica não vai voltar nos próximos anos
  • Um excelente material de introdução é Starting Forth
    Tem uma das ilustrações mais cativantes que já vi em um livro didático
    [0] https://www.forth.com/starting-forth/
  • Há muito tempo, quando o OS/2 foi lançado, um amigo me disse que “programas para OS/2 não podiam ser escritos em assembly, tinham que ser escritos em C”
    Em reação a isso, criei o Forth/2
    Era um compilador Forth de código nativo, com threading direto, para OS/2, escrito em assembly; Brian Matthewson escreveu um excelente manual, e conseguimos algumas dezenas de usuários
    [1] https://sourceforge.net/projects/forth2/
  • Mudando um pouco de assunto, lembro de ter lido a forma prototípica da apresentação original deste texto
    Era basicamente igual ao texto atual, mas com muito menos texto e bem mais lacunas
    Menciono isso porque aquele material também mostrava a beleza do minimalismo em termos de tecnologia de sites subjacente
    [0] http://ratfactor.com/forth/forth_talk_2023.html
    [1] http://ratfactor.com/minslides/
  • Acho interessante que também exista um compilador Forth em Rust. O material relacionado está em [1]
    O modo de uso ainda parece um pouco obscuro[2], mas isso já apareceu por aqui antes[3], e a implementação parece sólida
    Não é uma VM Forth com REPL, mas é uma impressionante implementação de máquina virtual
    Se FORTH for uma máquina virtual, faz tempo que penso que talvez seja a escolha ideal quando se precisa de um sistema pequeno e eficiente para gerenciar dados em streaming com desempenho próximo ao bare metal
    Também existe a vantagem de não precisar brigar com o sistema operacional
    Parece que, em essência, isso faria em uma CPU padrão o que um FPGA faz
    Mas estou imaginando um sistema especializado em que não seria necessário criar todos os drivers manualmente para conectar ao hardware necessário
    [1] https://docs.rs/rust-forth-compiler/latest/src/rust_forth_co...
    [2] https://docs.rs/fortraith/latest/fortraith/
    [3] https://news.ycombinator.com/item?id=23501474
  • Também implementei outro Forth por conta própria
    O objetivo não era copiar fielmente a ideia original; ele funciona de forma um pouco diferente
    Como o texto dizia que era possível encontrar Forth em todo lugar, deixo aqui também a minha implementação: https://github.com/loscoala/goforth
    A maior diferença é que, nesta variante de Forth, o texto-fonte é convertido inteiramente em bytecode, e não existe runtime no sentido clássico de Forth
    Por isso, é fácil traduzir o bytecode para C
    Eu uso esse Forth para gerar código C e então embuto esse código em outros softwares
    • Esse tipo de abordagem pode ser muito produtivo e inteligente, mas é preciso continuar ciente de que esse tipo de solução multilíngue tende a virar um pesadelo de manutenção no longo prazo
      Existe um projeto open source realmente muito bom que ajuda a treinar percepção auditiva e leitura à primeira vista, mas ele foi escrito em uma linguagem criada pelo autor, e essa linguagem compila para JavaScript
      O incômodo de configurar toda a toolchain era tão grande que, apesar de conhecer vários bugs, nunca criei coragem para corrigi-los
      https://sightreading.training/
      https://github.com/leafo/sightreading.training
      Este projeto foi escrito em uma linguagem chamada ‘Moonscript’: https://github.com/leafo/moonscript
      Moonscript compila para Lua, e Lua compila para JS
      É uma loucura. Uma loucura legal, mas ainda assim foi isso que me impediu de me tornar colaborador