interpretador BASIC -BASIC interpreter

Um exemplo de digitação de um programa popular em um interpretador BASIC (neste caso, HAMURABI )

Um interpretador BASIC é um interpretador que permite aos usuários inserir e executar programas na linguagem BASIC e foi, na primeira parte da era do microcomputador , o aplicativo padrão que os computadores iniciariam. Esperava-se que os usuários usassem o interpretador BASIC para digitar programas ou para carregar programas do armazenamento (inicialmente fitas cassete e depois disquetes ).

Os intérpretes BASIC são de importância histórica. O primeiro produto da Microsoft à venda foi um interpretador BASIC ( Altair BASIC ), que abriu caminho para o sucesso da empresa. Antes do Altair BASIC, os microcomputadores eram vendidos como kits que precisavam ser programados em código de máquina (por exemplo, o Apple I ). Durante o período Altair, os intérpretes BASIC foram vendidos separadamente, tornando-se o primeiro software vendido para indivíduos ao invés de organizações; Apple BASIC foi o primeiro produto de software da Apple. Depois do MITS Altair 8800 , esperava-se que os microcomputadores fossem enviados com seus próprios interpretadores BASIC (por exemplo, o Apple II , que tinha várias implementações do BASIC). Uma reação contra o preço do Altair BASIC da Microsoft também levou ao desenvolvimento precoce de software colaborativo, para implementações Tiny BASIC em geral e Palo Alto Tiny BASIC especificamente.

Os interpretadores BASIC caíram em desuso à medida que os computadores cresciam em poder e seus programas associados cresciam muito para serem digitados em um formato de distribuição razoável. O software veio cada vez mais pré-compilado e transmitido em disquete ou por meio de sistemas de quadro de avisos , tornando menos importante a necessidade de listas de fontes. Além disso, shells de comando cada vez mais sofisticados, como o MS-DOS e a GUI do Apple Macintosh , tornaram-se a principal interface de usuário e a necessidade do BASIC atuar como shell desapareceu. O uso de interpretadores BASIC como linguagem principal e interface para sistemas havia praticamente desaparecido em meados da década de 1980.

História

O BASIC ajudou a impulsionar a era do compartilhamento de tempo, tornou-se popular na era do microcomputador, depois desapareceu para se tornar apenas mais um aplicativo na era DOS e GUI e hoje sobrevive em alguns nichos relacionados ao desenvolvimento de jogos, retrocomputação e ensino.

Era do compartilhamento de tempo

Implementado pela primeira vez como um sistema compile-and-go em vez de um interpretador, o BASIC surgiu como parte de um movimento mais amplo em direção a sistemas de compartilhamento de tempo . A General Electric , tendo trabalhado no Dartmouth Time Sharing System e seu associado Dartmouth BASIC , escreveu seu próprio sistema operacional subjacente e lançou um sistema de compartilhamento de tempo on-line conhecido como Mark I, apresentando um compilador BASIC (não um intérprete) como um de seus principais produtos de venda. pontos. Outras empresas no campo emergente rapidamente seguiram o exemplo. No início dos anos 1970, o BASIC era amplamente universal em computadores mainframe de uso geral.

O sistema HP 2000 foi projetado para executar BASIC com tempo compartilhado como sua tarefa principal.

O BASIC, como uma linguagem simplificada projetada com a edição de linha integrada em mente, foi naturalmente adequado para portar para o mercado de minicomputadores , que surgia ao mesmo tempo que os serviços de tempo compartilhado. Essas máquinas tinham memória principal muito pequena , talvez tão pouco quanto 4 KB na terminologia moderna, e não tinham armazenamento de alto desempenho como discos rígidos que tornam os compiladores práticos. Em contraste, um interpretador usaria menos recursos de computação, em detrimento do desempenho. Em 1968, a Hewlett Packard apresentou o HP 2000 , um sistema baseado em seu interpretador HP Time-Shared BASIC . Em 1969, Dan Paymar e Ira Baxter escreveram outro interpretador BASIC para o Data General Nova .

Uma resistência era a Digital Equipment Corporation (DEC), o fornecedor líder de minicomputadores. Eles lançaram uma nova linguagem conhecida como FOCAL , baseada no JOSS anterior desenvolvido em uma máquina DEC no Stanford Research Institute no início dos anos 1960. O JOSS era semelhante ao BASIC em muitos aspectos, e o FOCAL era uma versão projetada para rodar em sistemas de memória muito pequenos, notavelmente o PDP-8 , que geralmente vinha com 4 KB de memória principal . No final da década de 1960, os vendedores da DEC, especialmente no departamento de vendas educacionais, descobriram que seus clientes em potencial não estavam interessados ​​no FOCAL e estavam procurando por seus sistemas em outro lugar. Isso levou David H. Ahl a contratar um programador para produzir um BASIC para o PDP-8 e outras máquinas DEC. Em um ano, todo o interesse por alternativas como JOSS e FOCAL havia desaparecido.

era do microcomputador

A introdução dos primeiros microcomputadores em meados da década de 1970 continuou o crescimento explosivo do BASIC, que tinha a vantagem de ser bastante conhecido pelos jovens designers e entusiastas de computador que se interessavam por microcomputadores, muitos dos quais tinham visto o BASIC em minis. ou mainframes. BASIC era uma das poucas linguagens que era de alto nível o suficiente para ser usada por pessoas sem treinamento e pequena o suficiente para caber nos microcomputadores da época. Em 1972, a HP apresentou a calculadora de mesa programável HP 9830A com um interpretador BASIC Plus em memória somente leitura (ROM).

Em junho de 1974, Alfred Weaver, Michael Tindall e Ronald Danielson, da Universidade de Illinois em Urbana-Champaign, provaram que era possível produzir "A BASIC Language Interpreter for the Intel 8008 Microprocessor", em seu artigo de mesmo nome, embora seus O aplicativo foi implantado em um simulador 8008 para o IBM 360/75 e exigiu 16 KB.

Altair 8K BASIC em fita de papel

Em janeiro de 1975, o Altair 8800 foi anunciado e iniciou a revolução dos microcomputadores . Uma das primeiras versões do BASIC para microcomputadores foi co-escrita por Gates, Allen e Monte Davidoff para sua empresa recém-formada, a Micro-Soft. Isso foi lançado pelo MITS em formato de fita perfurada para o Altair 8800 logo após a própria máquina, apresentando o BASIC como a linguagem principal para os primeiros microcomputadores.

Em março de 1975, Steve Wozniak participou da primeira reunião do Homebrew Computer Club e começou a formular o projeto de seu próprio computador. Os membros do clube ficaram entusiasmados com o Altair BASIC. Wozniak concluiu que sua máquina teria que ter um BASIC próprio. Na época, ele trabalhava na Hewlett Packard e usava o dialeto do minicomputador, HP Time-Shared BASIC , como base para sua própria versão. O Integer BASIC foi lançado em cassete para o Apple I e foi fornecido em ROM quando o Apple II foi lançado no verão de 1977.

Outros membros do Homebrew Computer Club começaram a distribuir cópias do Altair BASIC em fita de papel, fazendo com que Gates escrevesse sua Carta Aberta aos Hobbyists , reclamando desse exemplo inicial de pirataria de software . Parcialmente em resposta à carta de Gate, e parcialmente para fazer um BASIC ainda menor que rodaria utilmente em máquinas de 4 KB, Bob Albrecht instou Dennis Allison a escrever sua própria variação da linguagem. Como projetar e implementar uma versão simplificada de um interpretador para a linguagem BASIC foi abordado em artigos de Allison nas três primeiras edições trimestrais do boletim informativo da People's Computer Company publicado em 1975 e implementações com código-fonte publicadas no Dr. Dobb's Journal of Tiny BASIC Calistenia e Ortodontia: Running Light Sem Overbyte . Isso levou a uma grande variedade de Tiny BASICs com recursos adicionais ou outras melhorias, com versões bem conhecidas de Tom Pittman e Li-Chen Wang , ambos membros do Homebrew Computer Club. Tiny BASIC foi publicado abertamente e Wang cunhou o termo "copyleft" para encorajar outros a copiar seu código-fonte. Hobbyists e profissionais criaram suas próprias implementações, tornando o Tiny BASIC um exemplo de projeto de software livre que existia antes do movimento do software livre .

Muitas empresas desenvolveram interpretadores BASIC. Em 1976, o SCELBI introduziu o SCELBAL para o 8008 e a Universidade de Idaho e o Lawrence Livermore Laboratory anunciaram que publicariam no domínio público LLL BASIC, que incluía suporte de ponto flutuante. Em 1977, o Apple II e o TRS-80 Modelo I tinham cada um duas versões do BASIC, uma versão menor introduzida com os lançamentos iniciais das máquinas e uma versão licenciada da Microsoft introduzida posteriormente conforme o interesse nas plataformas aumentava.

Hello World , com vídeo inverso e caractere de sino , executado e listado no Applesoft BASIC

A Microsoft portou seu interpretador para o MOS 6502 , que rapidamente se tornou um dos microprocessadores mais populares da era de 8 bits. Quando novos microcomputadores começaram a aparecer, como o Commodore PET , seus fabricantes licenciavam um Microsoft BASIC, customizado para as capacidades do hardware. Em 1978, o MS BASIC era um padrão de fato e praticamente todos os computadores domésticos da década de 1980 o incluíam na ROM . Em 1980, como parte de um acordo de licenciamento maior que incluía outras linguagens e PC-DOS , a IBM rejeitou uma proposta da Atari e, em vez disso, licenciou o MS-BASIC sobre sua própria implementação, eventualmente lançando quatro versões do IBM BASIC , cada uma muito maior do que os intérpretes anteriores ( por exemplo, Cartridge BASIC levou 40 KB). Don Estridge , líder da equipe IBM PC , disse: "A IBM tem um BASIC excelente - é bem recebido, roda rápido em computadores mainframe e é muito mais funcional do que BASICs de microcomputador... os usuários eram infinitesimais em comparação com o número de usuários do Microsoft BASIC. O Microsoft BASIC tinha centenas de milhares de usuários em todo o mundo. Como você vai argumentar contra isso?" (Consulte Microsoft BASIC para obter o histórico subsequente dessas diferentes implementações.)

Muitos fornecedores "discutiram com isso" e usaram outras empresas ou escreveram seus próprios intérpretes. Em setembro de 1978, a Shepardson Microsystems estava finalizando o Cromemco 16K Structured BASIC para as máquinas de ônibus Cromemco S-100 baseadas em Z80 . Paul Laughton e Kathleen O'Brien então criaram o Atari BASIC como essencialmente uma versão simplificada do Cromemco BASIC portado para o 6502. Em 1979, Warren Robinett desenvolveu o cartucho de programação BASIC para Atari, Inc. , embora ele suportasse apenas programas com 9 linhas de código (64 caracteres no total). Também em 1979, a Texas Instruments lançou o TI BASIC (TI 99/4A) com seu TI-99/4 , que venderia quase 3 milhões de sistemas quando reformulado como TI-99/4A. Sinclair BASIC foi desenvolvido para o ZX-80 por John Grant e Steve Vickers da Nine Tiles. Em 1980, Sophie Wilson , da Acorn Computers, desenvolveu o Atom BASIC , que mais tarde evoluiu para o BBC BASIC , um dos primeiros intérpretes a oferecer programação BASIC estruturada, com procedimentos e funções nomeados / , loops e estruturas inspiradas no COMAL . Jan Jones desenvolveu o SuperBASIC , outro BASIC britânico que suporta programação estruturada, para o Sinclair QL . Em 1983, Randall Hyde desenvolveu o SmartBASIC para o Coleco Adam . Richard Clayton, Chris Hall e Paul Overell desenvolveram o Mallard BASIC para o BBC Micro e o Locomotive BASIC para o Amstrad CPC , ambos suportando comandos para um sistema de arquivos indexado ISAM . Em 1985, a MetaComCo lançou ABasiC para Amiga e ST BASIC para Atari ST . DEF PROCDEF FNREPEAT UNTILIF THEN ELSE

Em 1978, David Lien publicou a primeira edição de The BASIC Handbook: An Encyclopedia of the BASIC Computer Language , documentando palavras-chave em mais de 78 computadores diferentes. Em 1981, a segunda edição documentou palavras-chave de mais de 250 computadores diferentes, mostrando o crescimento explosivo da era do microcomputador.

Intérpretes como aplicativos

Com o surgimento dos sistemas operacionais de disco e, posteriormente, das interfaces gráficas do usuário , os interpretadores BASIC tornaram-se apenas um aplicativo entre muitos, em vez de fornecer o primeiro prompt que um usuário pode ver ao ligar um computador.

Em 1983, o computador portátil TRS-80 Modelo 100 estreou, com sua implementação do Microsoft BASIC notável por dois motivos. Primeiro, os programas eram editados usando o editor de texto simples, TEXT, em vez de digitados linha por linha (mas os números das linhas ainda eram necessários). Em segundo lugar, este foi o último produto da Microsoft que Bill Gates desenvolveu pessoalmente.

Também em 1983, a Microsoft começou a empacotar o GW-BASIC com o DOS. Funcionalmente idêntico ao IBM BASICA , seu interpretador BASIC era um executável totalmente autocontido e não precisava do Cassette BASIC ROM encontrado no IBM PC original . De acordo com Mark Jones Lorenzo, dado o escopo da linguagem, "GW-BASIC é indiscutivelmente o ne plus ultra da família Microsoft de BASICs numerados de linha que remonta ao Altair - e talvez até mesmo do BASIC numerado de linha em geral." Com o lançamento do MS-DOS 5.0, o lugar do GW-BASIC foi ocupado pelo QBasic .

O MacBASIC apresentava um ambiente de desenvolvimento totalmente interativo para o computador Macintosh original e foi desenvolvido por Donn Denman, Marianne Hsiung, Larry Kenyon e Bryan Stearns. O MacBASIC foi lançado como software beta em 1985 e foi adotado para uso em locais como o departamento de ciência da computação do Dartmouth College , para uso em um curso introdutório de programação. Ele estava fadado a ser o segundo BASIC desenvolvido pela Apple morto em favor de um Microsoft BASIC. Em novembro de 1985, a Apple encerrou abruptamente o projeto como parte de um acordo com a Microsoft para estender a licença do BASIC no Apple II .

O BASIC chegou a alguns sistemas de videogame, como o Nintendo Famicom .

Os intérpretes BASIC não foram apenas um desenvolvimento americano/britânico. Em 1984, a Hudson Soft lançou o Family BASIC no mercado japonês para o console de videogame Family Computer da Nintendo, uma implementação somente de número inteiro projetada para programação de jogos, baseada no Hudson Soft BASIC para o Sharp MZ80 (com palavras-chave em inglês). Turbo-Basic XL é um superconjunto compatível do Atari BASIC, desenvolvido por Frank Ostrowski e publicado na edição de dezembro de 1985 da revista de informática alemã Happy Computer , tornando-o um dos últimos intérpretes publicados como um programa de digitação . A linguagem incluía um compilador além do interpretador e apresentava comandos de programação estruturada. Várias versões modificadas trabalhando com diferentes sistemas DOS foram lançadas por outros autores. Na França, François Lionet e Constantin Sotiropoulos desenvolveram dois intérpretes BASIC com foco em multimídia: STOS BASIC para o Atari ST , em 1988, e AMOS BASIC para o Amiga , em 1990.

Em maio de 1991, a Microsoft lançou o Visual Basic , uma linguagem de programação orientada a eventos de terceira geração conhecida por seu modelo de programação COM ( Component Object Model ). O Visual Basic suportava o desenvolvimento rápido de aplicativos (RAD) de aplicativos de interface gráfica do usuário (GUI) , acesso a bancos de dados usando Data Access Objects , Remote Data Objects ou ActiveX Data Objects e criação de controles e objetos ActiveX . O Visual Basic foi usado para desenvolver aplicativos internos proprietários, bem como aplicativos publicados.

Nicho BÁSICO

Em 1993, a Microsoft lançou o Visual Basic for Applications , uma linguagem de script para aplicativos do Microsoft Office , que substitui e expande as habilidades de linguagens de programação de macro específicas de aplicativos anteriores , como o WordBASIC do Word (que foi introduzido em 1989).

Em 1996, a Microsoft lançou o VBScript como uma alternativa ao JavaScript para adicionar funcionalidade interativa do lado do cliente a páginas da Web visualizadas com o Internet Explorer .

Em 1999, Benoît Minisini lançou Gambas como uma alternativa para desenvolvedores de Visual Basic que decidiram migrar para o Linux .

Em 2000, Lee Bamber e Richard Vanner lançaram o DarkBASIC , um sistema de criação de jogos para o Microsoft Windows , com IDE e ferramentas de desenvolvimento.

Em 2001, SmallBASIC foi lançado para o Palm PDA . Outro interpretador BASIC para Palm foi o HotPaw BASIC, um desdobramento do Chipmunk Basic .

Em 2002, Emmanuel Chailloux, Pascal Manoury e Bruno Pagano publicaram um Tiny BASIC como exemplo de desenvolvimento de aplicações com Objective Caml .

Em 2011, a Microsoft lançou o Small Basic (distinto do SmallBASIC), juntamente com um currículo de ensino e um guia introdutório, projetado para ajudar os alunos que aprenderam linguagens de programação visual , como Scratch , a aprender programação baseada em texto. O IDE associado fornece um ambiente de programação simplificado com funcionalidades como realce de sintaxe , conclusão de código inteligente e acesso à documentação no editor. A linguagem tem apenas 14 palavras-chave. Em 2019, a Microsoft anunciou o Small Basic Online (SBO), permitindo que os alunos executem programas a partir de um navegador da web .

Em 2014, Robin H. Edwards lançou o Arduino BASIC para o Arduino , e agora uma implementação amplamente bifurcada. Outra implementação com o mesmo nome foi adaptada do Palo Alto Tiny BASIC em 1984 por Gordon Brandly para seu 68000 Tiny BASIC, posteriormente portado para C por Mike Field.

BÁSICO Móvel para Android

Muitos intérpretes BASIC estão agora disponíveis para smartphones e tablets através da Apple App Store ou Google Play Store para Android.

Hoje, codificar interpretadores BASIC tornou-se parte do hobby da retrocomputação . Linguagens de programação de alto nível em sistemas com extensa RAM simplificaram a implementação de interpretadores BASIC. Por exemplo, o gerenciamento de linha é simples se sua linguagem de implementação suporta matrizes esparsas , o gerenciamento de variáveis ​​é simples com matrizes associativas e a execução do programa é fácil com funções eval . Como exemplos, veja o projeto de código aberto Vintage BASIC, escrito em Haskell ou o OCaml Tiny BASIC .

Vendas e distribuição

Inicialmente, os intérpretes eram empacotados com hardware de computador ou desenvolvidos como um serviço personalizado, antes que uma indústria de produção de software empacotado de forma independente para organizações surgisse no final dos anos 1960. Os interpretadores BASIC foram vendidos separadamente dos microcomputadores, depois integrados, antes de serem vendidos como aplicativos novamente na era DOS.

Texto da legenda
Ano meios de comunicação Exemplo
1975 Fita de papel Altair BÁSICO
1975 programa de digitação Tiny BASIC Estendido
1976 Fita cassete Apple I BÁSICO
1977 Disquete ROM MICRO BÁSICO
1977 ROM Número inteiro BÁSICO
1983 Disquete GW-BASIC
1995 CD-ROM Visual Basic 4.0
2008 Loja de aplicativos Vários

À medida que o mercado mudou para ROMs, o tamanho da ROM passou a dominar as decisões sobre o tamanho de um interpretador BASIC. Como a RAM era vendida como chips de 4 KB, o Altair BASIC foi inicialmente empacotado em edições separadas para 4K, 8K e 12K; isso foi transferido para os chips ROM, pois os fabricantes decidiriam quantos chips ROM poderiam caber em seu projeto, dadas as metas de preço e outras restrições.

Compiladores vs. interpretadores

Compiladores vs. Interpretadores
Aspecto Compilador Intérprete
Otimizado para Desempenho Uso de memória
Velocidade de execução Mais rápido Mais devagar
Uso de memória Mais alto Mais baixo
Armazenamento secundário Obrigatório Opcional
Verificação de erros Antes da execução Durante a execução
Código fonte Não incorporado no executável Necessário para executar

A primeira implementação do BASIC, Dartmouth BASIC , foi um compilador. Geralmente, os compiladores examinam o programa inteiro em um processo de várias etapas e produzem um segundo arquivo que é diretamente executável na linguagem de máquina subjacente do computador host , sem referência ao código-fonte. Esse código geralmente é composto de chamadas para rotinas pré-escritas no sistema de tempo de execução da linguagem . O executável normalmente será menor que o código-fonte que o criou.

A principal desvantagem dos compiladores, pelo menos no contexto histórico, é que eles requerem grandes quantidades de memória temporária. À medida que o compilador funciona, ele produz um arquivo de saída cada vez maior que é mantido na memória junto com o código-fonte original. Memória adicional para pesquisas temporárias, principalmente números de linha no caso de BASIC, aumenta o requisito de memória. Os computadores da época tinham quantidades muito pequenas de memória; em termos modernos, um mainframe típico pode ter cerca de 64 KB. Em um sistema de compartilhamento de tempo, o caso da maioria dos BASICs da década de 1960, essa memória era compartilhada entre muitos usuários.

Para fazer um compilador funcionar, os sistemas precisavam ter algum tipo de armazenamento secundário de alto desempenho , geralmente um disco rígido . A edição do programa ocorreu em um ambiente dedicado que gravou o código-fonte do usuário em um arquivo temporário. Quando o usuário executava o programa, o editor saía e executava o compilador, que lia aquele arquivo e produzia o código executável e, finalmente, o compilador saía e executava o programa resultante. Dividir a tarefa dessa maneira reduziu a quantidade de memória necessária para qualquer uma das partes do sistema BASIC geral; a qualquer momento, apenas o editor, compilador ou tempo de execução precisava ser carregado, o restante ficava no armazenamento.

Enquanto os mainframes tinham pequenas quantidades de memória, os minicomputadores tinham quantidades ainda menores: sistemas de 4 e 8 KB eram típicos na década de 1960. Porém, muito mais importante, os minicomputadores tendiam a carecer de qualquer forma de armazenamento de alto desempenho; a maioria dos primeiros designs usava fita perfurada como sistema de armazenamento primário, e os sistemas de fita magnética eram para o segmento superior do mercado. Nesse ambiente, um sistema que gravasse o código-fonte, o compilasse e executasse o resultado levaria minutos. Devido a essas restrições, os intérpretes proliferaram.

Em última análise, os intérpretes executam as mesmas tarefas básicas dos compiladores, lendo o código-fonte e convertendo-o em instruções executáveis ​​que chamam funções de tempo de execução. A principal diferença é quando eles executam as várias tarefas. No caso de um compilador, todo o código-fonte é convertido durante o que parece ao usuário como uma única operação, enquanto um interpretador converte e executa o código-fonte uma instrução por vez. O código de máquina resultante é executado, em vez da saída, e então esse código é descartado e o processo é repetido com a próxima instrução. Isso dispensa a necessidade de algum tipo de armazenamento secundário enquanto um executável está sendo criado. A principal desvantagem é que você não pode mais separar as diferentes partes do processo geral - o código necessário para converter a fonte em operações de máquina deve ser carregado na memória junto com o tempo de execução necessário para realizá-lo e, na maioria dos casos, o editor de código-fonte também.

Produzir uma linguagem com todos esses componentes que caiba em uma pequena quantidade de memória e ainda tenha espaço para o código-fonte do usuário é um grande desafio, mas elimina a necessidade de armazenamento secundário e foi a única solução prática para os primeiros minicomputadores e a maioria dos a história da revolução do computador doméstico .

Desenvolvimento

Projeto de linguagem

O design da linguagem para os primeiros intérpretes geralmente envolvia simplesmente referenciar outras implementações. Por exemplo, as referências de Wozniak para BASIC foram um manual HP BASIC e uma cópia de 101 BASIC Computer Games . Com base nessas fontes, Wozniak começou a esboçar um gráfico de sintaxe para a linguagem. Ele não sabia que o BASIC da HP era muito diferente da variedade DEC BASIC usada em 101 Games . As duas linguagens diferiam principalmente em termos de manipulação de strings e estruturas de controle. O Data General Business Basic , uma implementação somente de números inteiros, foi a inspiração para o Atari BASIC.

Em contraste, Dennis Allison , membro do corpo docente de Ciência da Computação da Universidade de Stanford , escreveu uma especificação para uma versão simples da linguagem. Allison foi instado a criar o padrão por Bob Albrecht do Homebrew Computer Club , que tinha visto o BASIC em minicomputadores e sentiu que seria a combinação perfeita para novas máquinas como o Altair. O projeto proposto por Allison usava apenas aritmética inteira e não suportava arrays ou manipulação de strings. O objetivo era que o programa coubesse em 2 a 3 kilobytes de memória. O design geral do Tiny BASIC foi publicado na edição de setembro de 1975 do boletim informativo da People's Computer Company (PCC).

A gramática está listada abaixo na forma Backus-Naur . Na listagem, um asterisco (" *") denota zero ou mais objetos à sua esquerda — exceto o primeiro asterisco na definição de " term", que é o operador de multiplicação; objetos de grupo de parênteses; e um epsilon (" ε") significa o conjunto vazio. Como é comum na notação gramatical de linguagem de computador, a barra vertical (" |") distingue as alternativas, assim como a listagem em linhas separadas. O símbolo " CR" denota um retorno de linha .

    line ::= number statement CR | statement CR
 
    statement ::= PRINT expr-list
                  IF expression relop expression THEN statement
                  GOTO expression
                  INPUT var-list
                  LET var = expression
                  GOSUB expression
                  RETURN
                  CLEAR
                  LIST
                  RUN
                  END
 
    expr-list ::= (string|expression) (, (string|expression) )*
 
    var-list ::= var (, var)*
 
    expression ::= (+|-|ε) term ((+|-) term)*
 
    term ::= factor ((*|/) factor)*
 
    factor ::= var | number | (expression)
 
    var ::= A | B | C ... | Y | Z
 
    number ::= digit digit*
 
    digit ::= 0 | 1 | 2 | 3 | ... | 8 | 9
 
    relop ::= < (>|=) | > (<|=) | =

Essa sintaxe, por mais simples que fosse, acrescentou uma inovação: GOTOe GOSUBpoderia receber uma expressão em vez de um número de linha, fornecendo um GOTO atribuído em vez da instrução switch da ON-GOTO/GOSUBestrutura mais típica do BASIC.

O Sinclair BASIC usou como definição de linguagem o padrão Minimal BASIC do American National Standards Institute (ANSI) de 1978, mas era uma implementação incompleta apenas com aritmética inteira. O padrão ANSI foi publicado após o projeto da primeira geração de interpretadores para microcomputadores.

Arquitetura

Componentes comuns de um interpretador BASIC:

  • I/O e tratamento de interrupção
    • Teclado e tela
    • Entrada/saída de arquivo (se houver)
  • Editando rotinas
    • Linha de comando
    • Edição e armazenamento de programas
  • Rotinas de execução
    • Análise e interpretação
    • pacote aritmético
    • Gerenciamento de memória
      • Tabela de símbolos (se houver)
      • Coleta de lixo (se houver)

Codificação

Os primeiros microcomputadores careciam de ferramentas de desenvolvimento e os programadores desenvolviam seu código em minicomputadores ou à mão. Por exemplo, Dick Whipple e John Arnold escreveram Tiny BASIC Extended diretamente em código de máquina, usando octal . Robert Uiterwyk escreveu à mão MICRO BASIC para o SWTPC (um sistema 6800 ) em um bloco de notas. Steve Wozniak escreveu o código para Integer BASIC manualmente, traduzindo as instruções do código assembler em seus equivalentes de código de máquina e, em seguida, enviando o resultado para seu computador. (Por causa disso, o programa era muito difícil de mudar e Wozniak não foi capaz de modificá-lo com rapidez suficiente para Steve Jobs , que posteriormente licenciou o BASIC da Microsoft.)

Gates e Allen não tinham um sistema Altair para desenvolver e testar seu intérprete. No entanto, Allen havia escrito um emulador Intel 8008 para seu empreendimento anterior, Traf-O-Data , que rodava em um computador de compartilhamento de tempo PDP-10 . Allen adaptou esse emulador com base no guia do programador Altair e desenvolveu e testou o interpretador no PDP-10 de Harvard. Quando Harvard parou de usar esse sistema, Gates e Allen compraram tempo de computador de um serviço de compartilhamento de tempo em Boston para concluir a depuração do programa BASIC. Gates afirmou, em sua Carta Aberta aos Hobbyists em 1976, o valor do tempo de computador para o primeiro ano de desenvolvimento de software foi de $ 40.000.

Não que Allen não pudesse codificar manualmente em linguagem de máquina. Durante a aproximação final do aeroporto de Albuquerque em uma viagem para demonstrar o intérprete, Allen percebeu que havia esquecido de escrever um programa bootstrap para ler a fita na memória. Escrevendo em linguagem de máquina 8080, Allen terminou o programa antes de o avião pousar. Somente quando ele carregou o programa em um Altair e viu um prompt solicitando o tamanho da memória do sistema, ele soube que o interpretador funcionava no hardware do Altair.

Uma das versões mais populares do Tiny BASIC foi Palo Alto Tiny BASIC, ou PATB para abreviar. PATB apareceu pela primeira vez na edição de maio de 1976 do Dr. Dobbs , escrito em uma linguagem assembler personalizada com mnemônicos não padrão. Li-Chen Wang codificou seu interpretador em um sistema de tempo compartilhado com um montador genérico.

Uma exceção ao uso de assembly foi o uso de ALGOL 60 para o interpretador Paisley XBASIC para grandes sistemas Burroughs . Outra exceção, e programa de digitação , foi o Classic BASIC, escrito por Lennart Benschop em Forth e publicado na revista holandesa Forth Vijgeblad (edição nº 42, 1993).

O código-fonte dos interpretadores geralmente era de código aberto (como no Tiny BASIC) ou publicado posteriormente pelos autores. O código-fonte anotado completo e as especificações de design do Atari BASIC foram publicados como The Atari BASIC Source Book em 1983.

Máquinas virtuais

Alguns interpretadores BASIC foram codificados na representação intermediária de uma máquina virtual para adicionar uma camada de abstração e concisão acima da linguagem de máquina nativa .

Máquinas virtuais em proeminentes intérpretes BASIC
Dialeto do BASIC Linguagem da Máquina Virtual Máquina nativa
BÁSICO minúsculo Tiny BASIC Intermediate Language (TBIL) 6800
NIBL Linguagem Intermediária (IL) SC/MP
TI BÁSICA Linguagem de Programação Gráfica (GPL) TMS9900

Embora as máquinas virtuais tenham sido usadas em sistemas compile and go, como o BASIC-PLUS , elas eram apenas para executar o código BASIC, não para analisá-lo. O Tiny BASIC, em contraste, foi projetado para ser implementado como uma máquina virtual que analisava e executava (interpretava) instruções BASIC; em tal implementação, o próprio interpretador Tiny BASIC é executado em um interpretador de máquina virtual. A duração de todo o programa interpretador foi de apenas 120 operações de máquina virtual, consistindo em 32 comandos. Assim, a escolha de uma abordagem de máquina virtual economizou no espaço de memória e no esforço de implementação, embora os programas BASIC executados nela fossem executados de maneira um tanto lenta. (Consulte Tiny BASIC: Implementação em uma máquina virtual para obter um trecho e exemplos de comandos.) Embora a intenção do projeto fosse que o Tiny BASIC usasse uma máquina virtual, nem todas as implementações o faziam; aqueles que incluíam Tiny BASIC Extended, 6800 Tiny BASIC e NIBL.

Para sua TI-99 , a Texas Instruments projetou uma máquina virtual com uma linguagem chamada GPL, para "Graphic Programming Language". (Embora amplamente responsabilizado pelo desempenho lento do TI-BASIC , parte do problema era que a máquina virtual era armazenada na ROM gráfica, que tinha uma interface lenta de 8 bits.)

Um mal-entendido sobre as ROMs do Apple II levou alguns a acreditar que o Integer BASIC usava uma máquina virtual, uma linguagem de montagem personalizada contida nas ROMs da Apple e conhecida como Sweet16 . O Sweet16 é baseado em bytecodes executados em uma máquina virtual simples de 16 bits, de modo que a memória pode ser endereçada por meio de ponteiros indiretos de 16 bits e funções matemáticas de 16 bits calculadas sem a necessidade de traduzi-los para o 6502 de 8 bits subjacente de várias instruções código. No entanto, Sweet16 não foi usado pelo código básico do BASIC, embora tenha sido usado posteriormente para implementar vários utilitários, como uma rotina de renumeração de linha.

Edição e armazenamento de programas

Edição do programa

A maioria das implementações do BASIC da época agiam tanto como intérprete de linguagem quanto como editor de linha . Quando o BASIC estava em execução, um > prompt de comando era exibido onde o usuário podia inserir instruções. Isso era conhecido como " modo direto ". Na inicialização, um interpretador BASIC foi padronizado para o modo direto.

As instruções inseridas com números iniciais são inseridas no armazenamento do programa para "execução adiada", como novas linhas ou substituindo qualquer uma que possa ter o mesmo número anteriormente. As instruções inseridas sem um número de linha eram chamadas de comandos e executadas imediatamente. Números de linha sem instruções (ou seja, seguidos por um retorno de carro ) excluíam uma linha armazenada anteriormente.

Quando um programa está presente na memória e o usuário digita o RUNcomando, o sistema entra no "modo indireto". Nesse modo, um ponteiro é definido para apontar para a primeira linha do programa, por exemplo, a linha 10. O texto original dessa linha é recuperado do armazenamento e executado como se o usuário tivesse acabado de digitá-lo no modo direto. O ponteiro então avança para a próxima linha e o processo continua.

Diferentes implementações ofereciam outros recursos de edição de programas. O Altair BASIC 8K tinha um EDITcomando para mudar para o modo de edição de uma linha. Integer BASIC, também incluiu o AUTOcomando para inserir automaticamente números de linha em um determinado número inicial como AUTO 100, adicionando 10 ao último número a cada nova linha. AUTO 300,5começaria a numeração na linha 300 por cinco; 300, 305, etc. A numeração automática foi desativada digitando MAN. Alguns interpretadores ofereciam comandos ou utilitários de renumeração de linha.

Tokenização e codificação de linhas

Para economizar RAM e acelerar a execução, todos os interpretadores BASIC codificariam alguns caracteres ASCII de linhas em outras representações. Por exemplo, os números de linha foram convertidos em inteiros armazenados como bytes ou palavras , e as palavras-chave podem receber tokens de byte único (por exemplo, armazenar PRINTcomo o valor de byte 145, em MS-BASIC). Essas representações seriam então convertidas de volta em texto legível ao LISTexecutar o programa.

Codificação e tokenização em proeminentes intérpretes BASIC
Dialeto do BASIC Números de linha Palavras-chave Constantes Numéricas Nomes de variáveis
BÁSICO minúsculo Sim Não Não Não
Altair BÁSICO Sim Sim Não Não
Número inteiro BÁSICO Sim Sim Sim Não
Atari BASIC Sim Sim Sim Sim

Abreviaturas

Como alternativa à tokenização, para economizar RAM, as primeiras implementações do Tiny BASIC como Extended Tiny BASIC, Denver Tiny BASIC e MINOL truncaram as palavras-chave: PRfor PRINT, INfor INPUT, RETfor RETURN. As palavras-chave tradicionais completas não foram aceitas.

Em contraste, o Palo Alto Tiny BASIC aceitava palavras-chave tradicionais, mas permitia que qualquer palavra-chave fosse abreviada para sua string única mínima, com um ponto final. Por exemplo, PRINTpoderia ser digitado P., embora PR.outras variações também funcionassem. Este sistema foi mantido no Nível I BASIC para o TRS-80 , que usava PATB, e também foi encontrado no Atari BASIC e no BASIC de vários Sharp Pocket Computers .

Para expandir uma abreviação, o tokenizador Atari BASIC pesquisa em sua lista de palavras reservadas para encontrar a primeira que corresponde à parte fornecida. Os comandos mais usados ​​ocorrem primeiro na lista de palavras reservadas, com REMno início (pode ser digitado como .). Quando o programa for LISTeditado posteriormente, ele normalmente escreverá as palavras completas. O MS BASICs também permitia ?uma forma abreviada de PRINT, mas o expandia ao listar, tratando-o como uma abreviação, não como um sinônimo.

Tokenização

A maioria dos interpretadores BASIC realizam pelo menos alguma conversão do formato de texto original em vários formatos específicos de plataforma. Tiny BASIC estava no final simples: ele apenas converteu o número da linha de seu formato decimal em binário. Por exemplo, o número de linha "100" tornou-se um valor de byte único, $ 64, tornando-o menor para armazenar na memória, bem como mais fácil de procurar no código de máquina ( alguns designs de Tiny BASIC permitiam números de linha de apenas 1 a 254 ou 255, embora a maioria usasse valores de byte duplo e números de linha de pelo menos 1 a 999). O restante da linha foi deixado em seu formato de texto original. Na verdade, Dennis Allison argumentou que, dadas as restrições de memória, a tokenização exigiria mais código para implementar do que salvar.

Os MS-BASICs foram um pouco além, convertendo o número da linha em um valor de dois bytes e também convertendo palavras-chave, como FORou PRINT, em um valor de byte único, o "token". O valor do token tinha o bit alto definido para permitir que eles fossem facilmente distinguidos no tempo de execução. Todo o resto em uma linha foi deixado em seu formato original, por exemplo, a linha:

 10 FOR I=1 TO 10

seria tokenizado como:

 $64$81 I$B211$A410

Observe que o espaço entre FORe Ipermanece na linha tokenizada e os nomes de variáveis ​​e constantes não são tokenizados. O código que executou essa tokenização, conhecido como "o chunker", simplesmente copiou qualquer coisa que não reconhecesse como um token de volta para a saída, preservando os espaços como estão. Isso significava que PRINTAera armazenado em dois bytes, enquanto PRINT Aera armazenado em três bytes, e a remoção de espaços era uma maneira comum de melhorar o uso da memória. O Sinclair BASIC modificou isso ligeiramente, removendo espaços do código armazenado e inserindo-os no código durante um LIST, de forma que PRINTApareceria PRINT Aainda não ocupar o byte extra na memória.

Em contraste, o Integer BASIC converteria a linha 10 GOTO 100inteiramente em tokens que poderiam ser imediatamente lidos e executados. No MS-BASIC, a linha produziria $64 $89 100, e em tempo de execução o "100" teria que ser convertido para o formato de 16 bits toda vez que fosse encontrado. Por outro lado, o Integer BASIC também tokenizou variáveis ​​numéricas, evitando essa conversão e acelerando a execução. O valor de dois bytes resultante foi inserido no código tokenizado junto com um byte de prefixo indicando um número seguido. O prefixo era um valor entre $B0 e $B9 , sendo o último nibble do valor o primeiro dígito decimal no valor original. Literais de string, como "HELLO WORLD", foram codificados definindo o bit alto de cada caractere para que Afosse armazenado como $C1 . Os nomes das variáveis ​​foram convertidos da mesma maneira, com as letras codificadas para ter seu bit alto ativado e quaisquer dígitos no nome representados pelos correspondentes $B0 a $B9 , para que a variável A5fosse codificada como $C1B5 (não reduzido a um token). Houve várias outras otimizações; onde Microsoft BASIC tinha um token para a palavra-chave PRINT, Integer BASIC tinha três tokens: um se a palavra-chave fosse seguida por nenhum argumento, um se seguido por uma expressão aritmética e um se seguido por uma string literal.

Levando isso ainda mais longe, o tokenizer do Atari BASIC analisa toda a linha quando ela é inserida ou modificada. As constantes numéricas são analisadas em seu formato interno de 48 bits e, em seguida, colocadas na linha nesse formato, enquanto as strings são deixadas em seu formato original, mas prefixadas com um byte que descreve seu comprimento. As variáveis ​​têm armazenamento reservado conforme são encontradas, em vez de no tempo de execução, e seu nome é substituído por um ponteiro para seu local de armazenamento na memória. Shepardson referiu-se a esse conceito de tokenização inicial como um "interpretador de pré-compilação"; declarações com erros de sintaxe não puderam ser armazenadas e o usuário foi imediatamente solicitado a corrigi-los.

Tokenização no teclado

Teclado Sinclair ZX Spectrum
Combinações de teclas são usadas para inserir palavras-chave BASIC.

Alguns interpretadores, como os sistemas Sinclair, basicamente faziam o usuário fazer a tokenização fornecendo pressionamentos de tecla especiais para inserir palavras reservadas. Os comandos mais comuns precisam apenas de um pressionamento de tecla; por exemplo, pressionar apenas Pno início de uma linha em um Spectrum produz o comando completo PRINT. Comandos menos frequentes requerem sequências de teclas mais complexas. Como cada linha começa com uma palavra-chave, LETnão é opcional, depois que uma palavra-chave é digitada, o sistema volta a aceitar texto caractere por caractere. Uma vantagem dessa abordagem é que o tokenizador não pode confundir strings com palavras-chave. Por exemplo, permite que uma variável seja nomeada PRINTe exiba seu valor com PRINT PRINT.

Muitos " computadores de bolso " também usam um pressionamento de tecla (às vezes precedido por vários tipos de teclas shift) para produzir um byte (o token de palavra-chave) que representa uma palavra-chave BASIC inteira, como EXP, SQR, IF ou PEEK , como Sharp pocket conjuntos de caracteres de computador e TI-BASIC . A expansão BASIC para o Bally Astrocade também usa isso.

Gerenciamento de linha

Números de linha válidos nas primeiras implementações do BASIC
Faixa Dialeto
1 a 254 MINOL
1 a 255 Minúscula Nota de Design BÁSICO
2 a 255 Denver Tiny BASIC
0 a 999 UIUC BÁSICO
1 a 2045 DEZ BÁSICO-8
0 a 32767 LLL BÁSICO, NIBL
1 a 32767 Apple I BASIC , Nível I BASIC , Palo Alto Tiny BASIC
1 a 65535 Altair 4K BASIC , MICRO BASIC 1.3, 6800 Tiny BASIC, Tiny BASIC Estendido
1 a 99999 Dartmouth BASIC
1 a 999999 SCELBAL

Os números de linha válidos variaram de implementação para implementação, mas geralmente variavam de 1 a 32767.

A maior parte da memória usada pelos interpretadores BASIC era para armazenar a própria listagem do programa. As instruções numeradas foram armazenadas em ordem sequencial em uma matriz esparsa implementada como uma coleção linear (tecnicamente não é uma lista , pois nenhum número de linha pode ocorrer mais de uma vez).

Muitas implementações do Tiny BASIC armazenavam as linhas da seguinte forma:

  • Equivalente binário do número de linha (um ou dois bytes, dependendo do intervalo de números de linha válidos suportados)
  • Declaração de origem ASCII (comprimento variável)
  • Retorno de carro (um byte, definido como 13)

Microsoft BASIC, começando com Altair BASIC, linhas armazenadas da seguinte forma:

  • Ponteiro para a próxima linha (dois bytes)
  • Equivalente binário do número da linha (dois bytes, sem sinal)
  • Instrução de origem tokenizada (comprimento variável)
  • Nulo (um byte, definido como 0)

LLL BÁSICO:

  • Equivalente binário do número da linha (dois bytes)
  • Avançar o ponteiro para a próxima linha sequencial (dois bytes)
  • Comprimento da instrução de origem ASCII (um byte)
  • Declaração de origem ASCII (comprimento variável)

O comprimento máximo de uma linha variou: 64 caracteres em Palo Alto Tiny BASIC, incluindo a representação decimal do número da linha; 120 caracteres em Atari BASIC; 128 caracteres em Integer BASIC; e 255 caracteres em MS-BASIC (sem incluir o número da linha).

Os intérpretes procurariam no programa uma linha por vez, olhando para cada número de linha. Se fosse menor que o número da nova linha, as linhas posteriores seriam movidas na memória para liberar espaço para o espaço necessário para a nova linha. Se fosse o mesmo número de linha e não exatamente o mesmo comprimento, as linhas subsequentes precisariam ser movidas para frente ou para trás. (Como a ordem sequencial sempre foi mantida na memória, essas não eram listas encadeadas .)

No Tiny BASIC, essas pesquisas exigiam a verificação de cada byte em uma linha: o ponteiro seria incrementado repetidamente até que um retorno de carro fosse encontrado, para encontrar o byte antes da próxima linha. Em Altair BASIC e LLL BASIC, por outro lado, o ponteiro seria definido para o início da próxima linha sequencial; isso era muito mais rápido, mas exigia dois bytes por linha. Dado que se presumia que os programas Tiny BASIC tinham 4 KB ou menos de tamanho, isso estava de acordo com a filosofia geral de design do Tiny BASIC de negociar desempenho em favor de minimizar o uso de memória.

Quando o usuário digitava LISTna linha de comando, o sistema fazia um loop sobre a matriz de linhas, usando um desses métodos, convertia o número da linha de volta ao formato decimal e, em seguida, imprimia o restante do texto na linha, decodificando todos os tokens ou outras representações codificadas.

À medida que os desenvolvedores adicionavam construções de programação estruturada ao BASIC, eles geralmente eliminavam completamente a necessidade de números de linha e adicionavam editores de texto e, posteriormente, ambientes de desenvolvimento integrados .

Variáveis ​​e tipos de dados

nomes de variáveis

O Dartmouth BASIC e o HP-BASIC limitaram os nomes das variáveis ​​a no máximo dois caracteres (uma única letra ou uma letra seguida por um dígito; por exemplo, A a Z9). O MS-BASIC permitia nomes variáveis ​​de uma letra seguida por uma letra ou dígito opcional (por exemplo, A a ZZ), mas ignorava os caracteres subsequentes: assim, era possível escrever inadvertidamente um programa com as variáveis ​​"LOSS" e "LOAN", que seriam tratados como sendo iguais; atribuir um valor a "LOAN" substituiria silenciosamente o valor pretendido como "LOSS".

Integer BASIC era incomum em suportar qualquer nome de variável de comprimento (por exemplo, SUM, GAMEPOINTS, PLAYER2), desde que não contivesse uma palavra reservada. Palavras-chave não podiam ser usadas em variáveis ​​em muitos dos primeiros BASICs; "SCORE" seria interpretado como "SC" OR "E", onde OR era uma palavra-chave.

As variáveis ​​de string são geralmente distinguidas em muitos dialetos de microcomputadores do BASIC por terem $ como sufixo em seus nomes, e os valores geralmente são identificados como strings por serem delimitados por "aspas duplas". Implementações posteriores usariam outra pontuação para especificar o tipo de uma variável: A% para inteiro, A! para precisão simples e A# para precisão dupla .

Com exceção de arrays e (em algumas implementações) strings, e ao contrário de Pascal e outras linguagens de programação mais estruturadas, o BASIC não requer que uma variável seja declarada antes de ser referenciada. Os valores normalmente serão padronizados como 0 (da precisão apropriada) ou a string nula.

Tabela de símbolos

Como o Tiny BASIC usava apenas 26 variáveis ​​de uma única letra, as variáveis ​​podiam ser armazenadas como uma matriz sem armazenar seus nomes correspondentes, usando uma fórmula baseada no valor ASCII da letra como índice. Palo Alto Tiny BASIC deu um passo adiante: variáveis ​​'valores de dois bytes foram localizados na RAM dentro do programa, de bytes 130 (ASCII 65, 'A', vezes dois) a 181 (ASCII 90, 'Z', vezes dois , mais um para o segundo byte).

A maioria dos BASICs fornecia a capacidade de ter muito mais do que 26 variáveis ​​e, portanto, precisava de tabelas de símbolos , o que reservaria capacidade de armazenamento apenas para as variáveis ​​usadas.

No LLL BASIC, cada entrada na tabela de símbolos era armazenada da seguinte forma:

  • Nome da variável (byte 1: letra ASCII; byte 2: 0-9 ASCII ou binário 0)
  • Ponteiro de avanço (2 bytes)
  • Valor (4 bytes por elemento, 1 elemento se for uma variável escalar, caso contrário, tantos elementos quanto DIMensionado para uma matriz)

Ao contrário da maioria dos intérpretes BASIC, o UIUC BASIC tinha uma função de hash , fazendo hash pela letra do nome da variável/função/array e, em seguida, conduzindo uma pesquisa linear a partir daí. No UIUC BASIC, uma entrada da tabela de símbolos era:

  • Sinalizador (bit 0: entrada em uso; bit 6: função definida pelo usuário; bit 7: array}
  • Nome da variável (byte 1: letra ASCII; byte: 0-9 ASCII, " " ou "() ou nome da função (byte 1: letra ASCII ou token 154 para ; letra ASCII FN)
  • Valor (5 bytes):
    • Valor de ponto flutuante para um escalar
    • Definição de matriz (últimos 3 bytes: dimensão superior da primeira, segunda e terceira dimensão, todas assumidas para começar em 0)
    • Função do usuário (primeiros 2 bytes com o endereço da função; byte 3 é o deslocamento da tabela de símbolos para o parâmetro variável fictício na definição da função).

No Atari BASIC, um conjunto de ponteiros (endereços) indicava vários dados: os nomes das variáveis ​​eram armazenados na tabela de nomes de variáveis ​​(VNTP – 82, 83 16 ) e seus valores eram armazenados na tabela de valores de variáveis ​​(apontada em VVTP – 86, 87 16 ). Ao direcionar os nomes das variáveis ​​dessa maneira, uma referência a uma variável precisava de apenas um byte para endereçar sua entrada na tabela apropriada. Variáveis ​​de string tinham sua própria área.

Uma otimização de desempenho do BBC BASIC incluiu o uso de várias listas vinculadas para pesquisa de variáveis, em vez de uma única lista longa, como no Microsoft BASIC .

Gerenciamento de memória

Devido à pequena capacidade de RAM da maioria dos sistemas originalmente usados ​​para rodar interpretadores BASIC, técnicas inteligentes de gerenciamento de memória tiveram que ser empregadas. O Altair BASIC permite que os usuários recuperem o espaço para funções de trigonometria, se elas não estiverem sendo usadas durante uma sessão. O PATB colocou o início das sub-rotinas mais comuns na frente do programa para uso pelo RSTopcode 8080 de 1 byte em vez do CALLopcode de 3 bytes. No LLL BASIC, algumas variáveis ​​ocupavam os mesmos locais de memória, nos casos em que as diferentes variáveis ​​eram usadas apenas em modo de comando ou apenas em tempo de execução.

O vídeo geralmente era endereçável à memória e certas funções esotéricas estavam disponíveis pela manipulação de valores em valores de memória específicos. Por exemplo, os endereços 32 a 35 continham as dimensões da janela de texto (em oposição à janela gráfica) no Applesoft BASIC. O POKEcomando e a PEEKfunção (adaptados de monitores de código de máquina, como o monitor DECsystem-10 ) fornecem acesso direto à memória, para uma variedade de propósitos, especialmente para modificar registros de hardware mapeados em memória especiais para controlar funções específicas do computador, como a entrada /periféricos de saída. "Mapas de memória" (no sentido arcaico de listas de endereços de memória e suas funções) eram populares para uso com PEEK e POKE , sendo um dos mapas de memória mais conhecidos o livro Mapping the Atari , escrito por Ian Chadwick.

Algumas implementações do interpretador da Microsoft, por exemplo, aquelas executadas no TRS-80 Modelos I/III, exigiam que o usuário especificasse a quantidade de memória a ser usada pelo interpretador. Isso permitia que uma região da memória fosse reservada para a instalação de sub-rotinas em linguagem de máquina que pudessem ser chamadas pelo programa interpretado, para maior velocidade de execução. Quando os Modelos I/III são ligados, o usuário é saudado com o prompt "Tamanho da memória?" para este fim.

Matemática

O Integer BASIC, como o próprio nome indica, usa números inteiros como base para seu pacote matemático. Estes foram armazenados internamente como um número de 16 bits, little-endian (como é o 6502). Isso permitiu um valor máximo para qualquer cálculo entre -32767 e 32767. Os cálculos que resultaram em valores fora desse intervalo produziram um erro.

A maioria dos interpretadores Tiny BASIC (assim como Sinclair BASIC 4K) suportava matemática usando apenas números inteiros, sem suporte a ponto flutuante . O uso de números inteiros permitiu que os números fossem armazenados em um formato de 16 bits muito mais compacto, que poderia ser lido e processado mais rapidamente do que os formatos de ponto flutuante de 32 ou 40 bits encontrados na maioria dos BASICs da época. No entanto, isso limitou sua aplicabilidade como uma linguagem de uso geral.

As implementações do Business BASIC , como Data General Business Basic , também eram somente números inteiros, mas normalmente com uma precisão mais alta: "precisão dupla", ou seja, 32 bits (mais ou menos 2.147.483.648) e "precisão tripla" (mais ou menos 1,4x10 ^14).

Às vezes, outros formatos de número de computador eram usados. Por exemplo, o MINOL Tiny BASIC suportava apenas bytes não assinados , e o MICRO-BASIC Tiny BASIC usava Decimal Codificado Binário . Mas o ponto flutuante viria a predominar.

Ponto flutuante

Uma história resume por que o ponto flutuante foi considerado tão importante. O protótipo original do TRS-80 Modelo I executou a versão de domínio público de Li-Chen Wang do Tiny BASIC . Isso exigia apenas 2 KB de memória para o interpretador , deixando uma média de outros 2 KB livres para programas de usuário em layouts de memória comuns de 4 KB das máquinas anteriores. Durante uma demonstração para executivos, o então presidente da Tandy Corporation , Charles Tandy, tentou inserir seu salário, mas não conseguiu. Isso acontecia porque o Tiny BASIC usava inteiros assinados de 2 bytes com um valor máximo de 32.767. O resultado foi um pedido de matemática de ponto flutuante para a versão de produção. Isso levou à substituição do código inteiro de 16 bits existente por uma versão usando números de ponto flutuante de precisão única de 32 bits pelo funcionário da Tandy, Steve Leininger.

SCELBAL usou rotinas de ponto flutuante publicadas por Wadsworth em 1975 em Machine Language Programming para o 8008 baseado em um formato de 32 bits (quatro bytes) para cálculos numéricos, com uma mantissa de 23 bits , sinal de 1 bit para a mantissa, um sinal de 7 bits expoente de bit e sinal de 1 bit para o expoente. Estes foram organizados em ordem inversa, com o byte menos significativo da mantissa no primeiro byte, seguido pelo do meio e depois o byte mais significativo com o sinal no bit alto. O expoente veio por último, novamente com o sinal no bit alto. O manual fornece código de montagem bem documentado para todo o pacote matemático, incluindo pontos de entrada e notas de uso.

Os consultores eram normalmente levados a lidar com aritmética de ponto flutuante , um domínio especializado bem estudado e desenvolvido para as aplicações científicas e comerciais que caracterizaram os mainframes. Quando Allen e Gates estavam desenvolvendo o Altair BASIC, o colega estudante de Harvard Monte Davidoff os convenceu a mudar da aritmética inteira . Eles contrataram Davidoff para escrever um pacote de ponto flutuante que ainda pudesse caber dentro dos limites de memória de 4 KB. Steve Wozniak recorreu a Roy Rankin, da Universidade de Stanford, para implementar as funções transcendentais LOG, LOG10 e EXP; no entanto, Wozniak nunca terminou de adicionar suporte de ponto flutuante ao Integer BASIC. O LLL BASIC , desenvolvido na Universidade de Idaho por John Dickenson, Jerry Barber e John Teeter, recorreu a David Mead, Hal Brand e Frank Olken por seu suporte de ponto flutuante. Para UIUC BASIC, foi licenciado um pacote de ponto flutuante Datapoint 2200 .

Em contraste, os sistemas de tempo compartilhado geralmente dependiam de hardware. Por exemplo, o GE-235 foi escolhido para implementar a primeira versão do Dartmouth BASIC especificamente porque apresentava uma " Unidade Aritmética Auxiliar " para cálculos de ponto flutuante e precisão dupla.

Os primeiros intérpretes usavam formatos de 32 bits, semelhantes ao formato de ponto flutuante binário de precisão simples IEEE 754 , que especifica:

Aqui está o valor 0,15625 armazenado neste formato: Flutuar exemplo.svg

Embora os formatos de 32 bits fossem comuns nessa época, as versões posteriores do BASIC, começando com o Microsoft BASIC para o MOS 6502 , geralmente adotavam um formato de 40 bits (cinco bytes) para maior precisão.

Operadores e funções

Operadores infixos normalmente incluídos +(adição), -(subtração), *(multiplicação), /(divisão) e expoente usando o ^caractere. As operações relativas incluíam o conjunto padrão de =, >, <, >=, <=, e para "não igual" <>ou o inspirado no HP-TSB# . Operadores binários, como AND, ORe NOT, não estavam em todas as implementações, e alguns faziam álgebra booleana e outros não.

A edição inicial do Dartmouth BASIC incluía as seguintes funções: ABS( valor absoluto ), ATN( arco tangente ), COS( cosseno ), EXP( e elevado à potência), INT( truncar qualquer valor fracionário, retornando um inteiro), LOG( logaritmo ), RND( gerador de número pseudo-aleatório ) , SIN( seno ), SQR( raiz quadrada ) e TAN( tangente ). Também incluía a DEF FNinstrução para declarar funções de uma linha, que seriam então referidas como FNA(), FNB(), etc.

A RNDfunção foi a função mais difundida a ser suportada nos primeiros BASICs, embora as implementações variassem:

  • O Dartmouth's RNDignorou o parâmetro e sempre retornou um novo número pseudo-aleatório entre 0 e 1.
  • Altair BASIC e Microsoft BASICs posteriores usavam o sinal do parâmetro: Para RND(X), "X<0 inicia uma nova sequência de números aleatórios usando X. Chamar RND com o mesmo X inicia a mesma sequência de números aleatórios. X=0 fornece o último número aleatório gerado."
  • Sendo incapaz de retornar um BASIC decimal, apenas inteiro, em vez disso, usou o valor do parâmetro, normalmente para especificar um limite superior para a randomização; por exemplo, no próprio Integer BASIC, RND(6)+1simularia um lançamento de dado, retornando valores de 1 a 6.
  • Em contraste, em alguns BASICs TRS-80, o parâmetro era o limite superior que poderia ser retornado; por exemplo, RND(6)retornaria um valor de 1 a 6 e RND(1)sempre retornaria 1.

Matrizes

A segunda versão do Dartmouth BASIC suportava matrizes e operações com matrizes , úteis para a solução de conjuntos de equações algébricas lineares simultâneas; MAToperações com matrizes como atribuição, adição, multiplicação (de tipos de matrizes compatíveis) e avaliação de um determinante foram suportadas.

Em contraste, o Tiny BASIC, como inicialmente projetado, nem sequer tinha arrays, devido à memória principal limitada disponível nos primeiros microcomputadores , geralmente 4 KB, que tinha que incluir tanto o interpretador quanto o programa BASIC. O Palo Alto Tiny BASIC adicionou uma única matriz de inteiros de tamanho variável , cujo tamanho não precisava ser dimensionado, mas usava RAM não usada pelo interpretador ou pela listagem de programas, A().

O SCELBAL suportava vários arrays, mas juntos esses arrays não podiam ter mais de 64 itens. Matrizes com suporte BASIC inteiro de uma única dimensão, limitadas em tamanho apenas pela memória disponível. Tiny BASIC Extended suportava matrizes bidimensionais de até 255 por 255. Altair BASIC 4K suportava apenas matrizes (uma dimensão), enquanto a versão 8K suportava matrizes de até 34 dimensões.

Muitas implementações suportavam a prática Dartmouth BASIC de não exigir que um array fosse dimensionado, caso em que se supunha que ele tinha 11 elementos (0 a 10); por exemplo, {{{1}}}criaria a matriz de 11 elementos como efeito colateral.

O vetor dope de arrays variou de implementação para implementação. Por exemplo, o vetor dope de um array Altair BASIC 4K:

  • Nome da variável (2 bytes)
  • Tamanho dos elementos da matriz em bytes (2 bytes, portanto, 4 vezes o número de elementos, que era o limite superior mais um)

Em seguida, os próprios valores da matriz:

  • Valor do elemento 0 (4 bytes)
  • Valor do elemento 1 (4 bytes)
  • ...
  • Valor do elemento N (4 bytes)

As implementações que suportavam matrizes tinham que registrar o número de dimensões e o limite superior de cada dimensão. Além disso, como alguns intérpretes tinham apenas um tipo de dados (ponto flutuante ou inteiro), o vetor dope precisava apenas registrar o número de dimensões e o limite superior de cada dimensão. Os intérpretes com vários tipos de dados tiveram que registrar o tipo de dados da matriz.

Embora a Microsoft e outros BASICs suportassem matrizes, as operações de matriz não eram incorporadas, mas tinham que ser programadas explicitamente nos elementos da matriz.

Cordas

O Dartmouth BASIC original, alguns de seus descendentes imediatos e as implementações do Tiny BASIC careciam de manipulação de strings. Duas escolas concorrentes de manuseio de cordas evoluíram, iniciadas por HP e DEC, embora outras abordagens tenham surgido posteriormente. Estas exigiam diferentes estratégias de implementação.

Manipulação de strings em proeminentes intérpretes BASIC
Dialeto do BASIC Tipo Substrings
HP Time-Shared BÁSICO Comprimento fixo Fatiamento
DEC BASIC-PLUS Comprimento variável Funções
Dartmouth BASIC quarta edição Comprimento variável indexação de matriz
BÁSICO minúsculo Matriz inteira indexação de matriz

A manipulação de string mais simples copiava o HP Time-Shared BASIC e definia variáveis ​​de string como arrays de caracteres que precisavam ser DIMensionados antes do uso. As strings no HP TSB são tratadas como uma matriz de caracteres, até 72 no total, em vez de um único objeto de vários caracteres. Por padrão, eles recebem um caractere na memória e, se for necessária uma string de comprimento maior, eles devem ser declarados. Por exemplo, configurará uma string que pode conter no máximo 10 caracteres. DIM A$[10]

Substrings dentro de strings são acessadas usando uma notação " slicing ": ou , onde a substring começa com o caractere mais à esquerda especificado pelo índice L e continua até o caractere mais à direita especificado pelo índice R, ou a forma em que a substring começa no caractere mais à esquerda especificado pelo índice L e continua até o final da string. TSB aceita () ou [] de forma intercambiável. Índices de matriz e substring começam com 1. A$(L,R)A$[L,R]A$[L]

Isso contrasta fortemente com BASICs seguindo o padrão DEC que usa funções como LEFT$(), MID$()e RIGHT$()para acessar substrings. Posteriormente adotada pelo ANSI BASIC, a notação HP também pode ser usada no lado de destino de uma instrução LETou para modificar parte de um valor de string existente, por exemplo, ou , o que não pode ser feito com implementações anteriores de . INPUT100 A$[3,5]="XYZ"120 B$[3]="CHANGE ALL BUT FIRST TWO CHARS"LEFT$/MID$/RIGHT$

Versões posteriores do Dartmouth BASIC incluíam variáveis ​​de string. No entanto, eles não usaram as LEFT$/MID$/RIGHT$funções para manipular strings, mas usaram o CHANGEcomando que convertia a string de e para valores ASCII equivalentes. (Mais tarde adotado como está por DEC e adaptado por HP, que mudou a palavra-chave para CONVERT.) Além disso, pode-se usar aspas simples para converter uma constante numérica em um caractere ASCII, permitindo construir uma string em partes; A$='23 '64 '49 "DEF"produziu a string "ABCDEF", sem a necessidade da CHR$()função. Dartmouth BASIC Sixth Edition suportado SEG$(para MID$) e POS(para INSTR).

Integer BASIC, North Star BASIC e Atari BASIC imitaram a abordagem da HP, que novamente contrastou com o estilo encontrado em BASICs derivados de DEC , incluindo Microsoft BASIC , onde strings são um tipo intrínseco de comprimento variável.

Algumas das implementações do Tiny BASIC suportavam um ou mais arrays inteiros pré-definidos, que podiam ser usados ​​para armazenar códigos de caracteres, desde que a linguagem tivesse funcionalidade para entrada e saída de códigos de caracteres (por exemplo, Astro BASIC tinha KPe TVpara este propósito).

Coleta de lixo

Um exemplo de fragmentação externa

Ter strings utilizando uma quantidade fixa de memória independente do número de caracteres utilizados dentro delas, até no máximo 255 caracteres, pode ter desperdiçado memória mas teve a vantagem de evitar a necessidade de implementação de coleta de lixo do heap , uma forma de gerenciamento de memória usado para recuperar memória ocupada por strings que não estão mais em uso. Strings curtas que foram liberadas podem ser armazenadas no meio de outras strings, evitando que essa memória seja usada quando uma string mais longa for necessária.

Nos primeiros microcomputadores, com sua memória limitada e processadores lentos, a coleta de lixo do BASIC frequentemente causava pausas aparentemente aleatórias e inexplicáveis ​​no meio da operação do programa. Alguns interpretadores BASIC, como o Applesoft BASIC na família Apple II , verificam repetidamente os descritores de string para a string com o endereço mais alto para compactá-la em direção à memória alta, resultando em desempenho O(n 2 ) , que pode apresentar pausas na execução de programas intensivos em strings. A coleta de lixo era notoriamente lenta ou até mesmo quebrada em outras versões do Microsoft BASIC. Alguns sistemas operacionais que suportavam tarefas em segundo plano orientadas por interrupção, como TRSDOS/LS-DOS 6.x no TRS-80 Modelo 4 , exploravam períodos de inatividade do usuário (como os períodos de milissegundos entre pressionamentos de teclas e períodos após a atualização da tela de vídeo ) para processar a coleta de lixo durante a execução do programa BASIC.

Outras funcionalidades

Gráficos e som

A maioria dos intérpretes BASIC diferia amplamente em gráficos e som, que variavam dramaticamente de microcomputador para microcomputador. O Altair BASIC carecia de gráficos ou comandos de som, assim como as implementações do Tiny BASIC, enquanto o Integer BASIC fornecia um conjunto rico.

Nível I BASIC para o TRS-80 tinha um conjunto mínimo possível: CLS, para CLear Screen; SET(X,Y), que iluminou um local no visor; RESET(X,Y), que o desligou; e POINT(X,Y), que retorna 1 se um local estiver aceso, 0 se não estiver. As coordenadas podem ser qualquer expressão e variam de 0 a 127 para o eixo X e de 0 a 47 para o eixo Y. Somente exibição em preto e branco era suportada.

Em contraste, o Integer BASIC suportava gráficos coloridos, som simples e controladores de jogos. O modo gráfico foi ativado com a GRinstrução e desativado com TEXT. O desenho era modal e normalmente começava com a emissão de um comando para mudar a cor, o que era feito definindo uma pseudo-variável; COLOR=12definiria a cor do desenho para 12, verde claro. Pode-se então PLOT 10,10produzir um único ponto dessa cor, HLIN 0,39 AT 20desenhar uma linha horizontal na linha 20 que abrange a tela ou VLIN 5,15 AT 7desenhar uma linha vertical mais curta na coluna 7. A=SCRN X,Yretorna a cor da tela em X,Y.

conjunto gráfico de bloco de texto do ZX-81

Os fabricantes de hardware geralmente incluíam suporte proprietário para semigráficos , formas simples e ícones tratados como caracteres especiais . Os exemplos incluíam os gráficos de bloco do ZX-81 e os símbolos de cartão de ♠, ♣, ♥ e ♦ no conjunto de caracteres Commodore International PETSCII . O BASIC pode gerar esses símbolos usando arquivos PRINT CHR$();.

A Microsoft adicionou muitos comandos gráficos ao IBM BASIC : LINE, PSET​​(Pixel SET), PRESET(Pixel RESET), GET(armazena um retângulo da tela em uma matriz), PUT(exibe um segmento retangular armazenado), LOCATE(para mover o cursor de texto) e DRAW, que esboça formas usando uma sintaxe semelhante a LOGO . Bill Gates e Neil Konzen escreveram DONKEY.BAS , um jogo integrado, para demonstrar os gráficos coloridos e o som do intérprete .

entrada/saída

Outra área em que as implementações divergiram foi em palavras-chave para lidar com mídia (cassetes e disquetes), entrada de teclado e controladores de jogos (se houver).

Como os interpretadores BASIC baseados em ROM geralmente funcionam como shells para carregar em outros aplicativos, as implementações adicionam comandos relacionados a fitas cassete (por exemplo, CLOADe CSAVE), arquivos de disco binário (por exemplo, BLOAD, BSAVEe BRUN) e programas BASIC no disco (por exemplo, LOAD, SAVE, e CATALOG). As implementações Business BASIC adicionaram comandos para arquivos de acesso aleatório. (Mesmo os interpretadores BASIC baseados em ROM não foram projetados ou destinados a serem usados ​​como sistemas operacionais, e microcomputadores menores simplesmente não tinham nenhum sistema operacional.)

O Dartmouth BASIC não tinha um comando para obter entrada do teclado sem pausar o programa. Para dar suporte aos videogames , os BASICs adicionaram comandos proprietários para fazer isso: INKEY$era uma função no Microsoft BASIC que retornaria uma string vazia se nenhuma tecla fosse pressionada ou, caso contrário, um único caractere; KP(para KeyPress ) retornou o valor ASCII da entrada no Astro BASIC .

O Palo Alto Tiny BASIC carecia de strings, mas permitiria aos usuários inserir expressões matemáticas como resposta às INPUTdeclarações; definindo variáveis, como Y=1; N=0, o usuário pode responder “S” ou “1” ou mesmo "3*2-5" em um prompt sim/não.

Alguns sistemas suportavam controladores de jogos. Astro BASIC suportado JX()(posição horizontal do joystick especificada), JY()(posição vertical do joystick), KN()(status do botão) e TR()(status do gatilho). O Integer BASIC suportava um controlador de jogo , um controlador de remo , que tinha dois controladores em um único conector. A posição do controlador pode ser lida através da PDLfunção, passando o número do controlador, 0 ou 1, como A=PDL(0):PRINT A, retornando um valor entre 0 e 255.

O Integer BASIC carecia de comandos personalizados de entrada/saída e também carecia da DATAinstrução e do arquivo READ. Para obter dados dentro e fora de um programa, a funcionalidade de entrada/saída foi redirecionada para um slot de cartão selecionado com PR#xe IN#x, que redirecionou a saída ou entrada (respectivamente) para o slot numerado. A partir de então, os dados podem ser enviados para o cartão usando PRINTcomandos convencionais e lidos usando INPUT. A produção de sons foi realizada por PEEKmeio da localização mapeada na memória de um simples "bipe", -16336.

programação estruturada

Embora a programação estruturada , por meio dos exemplos de ALGOL 58 e ALGOL 60 , fosse conhecida por Kemeny e Kurtz quando eles projetaram o BASIC, eles adaptaram apenas o loop for, ignorando a instrução else, loop while, loop repeat, procedimentos nomeados, parâmetro passagem e variáveis ​​locais. Como resultado, os dialetos subseqüentes muitas vezes diferiam drasticamente nas palavras usadas para técnicas estruturadas. Por exemplo, WHILE...WEND(no Microsoft BASIC ), WHILE...ENDWHILE(no Turbo-Basic XL ) DO...LOOP WHILEe até mesmo WHILEcláusulas (ambos no BASIC-PLUS ).

Das implementações do Tiny BASIC, apenas a National Industrial Basic Language (NIBL) oferecia um comando de loop de qualquer tipo, DO/UNTIL. Isso ocorreu apesar do inventor do Tiny BASIC, Dennis Allison, lamentar publicamente o estado do BASIC.

O BBC BASIC foi um dos primeiros intérpretes de microcomputador a oferecer programação BASIC estruturada, com nomes DEF PROC/ DEF FNprocedimentos e funções, REPEAT UNTILloops e IF THEN ELSEestruturas inspiradas no COMAL . Os BASICs de segunda geração - por exemplo, SBASIC (1976), BBC BASIC (1981), True BASIC (1983), Beta BASIC (1983), QuickBASIC (1985) e AmigaBASIC (1986) - introduziram vários recursos no linguagem, principalmente relacionada à programação estruturada e orientada a procedimentos. Normalmente, a numeração de linhas é omitida da linguagem e substituída por rótulos (para GOTO ) e procedimentos para encorajar um design mais fácil e flexível. Além disso, foram introduzidas palavras-chave e estruturas para dar suporte à repetição, seleção e procedimentos com variáveis ​​locais.

O exemplo a seguir está no Microsoft QBASIC, a terceira implementação da Microsoft de um BASIC estruturado (seguindo o Macintosh BASIC em 1984 e o Amiga BASIC em 1985).

REM QBASIC example

REM Forward declaration - allows the main code to call a
REM    subroutine that is defined later in the source code
DECLARE SUB PrintSomeStars (StarCount!)

REM Main program follows
DO
   INPUT "How many stars do you want? (0 to quit) ", NumStars
   CALL PrintSomeStars(NumStars)
LOOP WHILE NumStars>0
END

REM subroutine definition
SUB PrintSomeStars (StarCount)
   REM This procedure uses a local variable called Stars$
   Stars$ = STRING$(StarCount, "*")
   PRINT Stars$
END SUB

Orientado a Objeto

O suporte inicial para programação orientada a objetos fornecia apenas a reutilização de objetos criados com outras linguagens, como o Visual Basic e o PowerBASIC suportavam o Windows Component Object Model . À medida que os interpretadores BASIC continuaram a evoluir, eles adicionaram suporte para recursos orientados a objetos, como métodos , construtores , alocação dinâmica de memória , propriedades e alocação temporária.

Montador incluído

As ROMs Integer BASIC também incluíam um monitor de código de máquina , "miniassembler " e desmontador para criar e depurar programas em linguagem assembly .

Uma das características únicas do BBC BASIC era o montador inline , permitindo aos usuários escrever programas em linguagem assembly para o 6502 e, posteriormente, para o Zilog Z80 , NS32016 e ARM . O montador era totalmente integrado ao interpretador BASIC e compartilhava variáveis ​​com ele, que podiam ser incluídas entre os caracteres [ e ], salvas via *SAVE e *LOAD e chamadas via comandos CALL ou USR. Isso permitiu que os desenvolvedores escrevessem não apenas código em linguagem assembly, mas também código BASIC para emitir linguagem assembly, tornando possível usar técnicas de geração de código e até mesmo escrever compiladores simples em BASIC.

Execução

Depuração

Como na maioria dos BASICs, os programas eram iniciados com o RUNcomando e, como era comum, podiam ser direcionados para um número de linha específico, como RUN 300. A execução pode ser interrompida a qualquer momento usando Ctrl+ C(ou BREAK como no TRS-80) e então reiniciada com CONTinue ( CONem Integer BASIC). Aproveitando os recursos exclusivos de programas interpretados (o código é processado em tempo real, uma instrução por vez, em contraste com os compiladores ), o usuário no console pode examinar dados variáveis ​​usando a instrução PRINT e alterar esses dados dinamicamente , em seguida, retome a execução do programa.

Para a execução passo a passo, a instrução TRONou TRACEpode ser usada no prompt de comando ou inserida no próprio programa. Quando ativado, os números de linha eram impressos para cada linha visitada pelo programa. O recurso pode ser desativado novamente com TROFFou NOTRACE.

Algumas implementações, como os interpretadores da Microsoft para as várias marcas do TRS-80, incluíam o comando ON ERROR GOSUB. Isso redirecionaria a execução do programa para um número de linha especificado para tratamento especial de erros.

Ao contrário da maioria dos BASICs, o Atari BASIC varreu a linha de programa recém-inserida e relatou erros de sintaxe imediatamente. Caso fosse encontrado algum erro, o editor reexibia a linha, destacando o texto próximo ao erro em vídeo inverso .

Em muitos interpretadores, incluindo o Atari BASIC, os erros são exibidos como códigos numéricos, com as descrições impressas no manual. Muitos MS-BASIC usavam abreviações de dois caracteres (por exemplo, SN para SYNTAX ERROR). Palo Alto Tiny BASIC e Level I BASIC usavam três palavras para mensagens de erro: "O QUÊ?" para erros de sintaxe, "COMO?" para erros de tempo de execução como GOTOs para uma linha que não existia ou estouros numéricos e "SORRY" para problemas de falta de memória.

Análise

Embora a linguagem BASIC tenha uma sintaxe simples, as expressões matemáticas não, suportando diferentes regras de precedência para parênteses e diferentes operadores matemáticos. O suporte a tais expressões requer a implementação de um analisador descendente recursivo .

Este analisador pode ser implementado de várias maneiras:

  • Como uma máquina virtual, conforme discutido acima para muitas implementações do Tiny BASIC. O valor da iniciativa Tiny BASIC estava em especificar uma implementação de um analisador.
  • Como uma máquina de estado finito , como no UIUC BASIC IUC, onde foi implementado como uma tabela de controle .
  • Diretamente no código, como em Palo Alto Tiny BASIC e Integer BASIC. No Integer BASIC, o interpretador de tempo de execução usava duas pilhas para execução: uma para palavras-chave de instrução e outra para avaliar os parâmetros. Cada instrução recebeu duas prioridades: uma que indicava onde deveria ocorrer em uma operação de várias etapas, como uma sequência de operações matemáticas para fornecer a ordem das operações , e outra que sugeria quando a avaliação deveria ocorrer, por exemplo, calculando valores internos de um fórmula entre parênteses. Quando as variáveis ​​eram encontradas, seus nomes eram analisados ​​e depois pesquisados ​​na tabela de símbolos. Caso não fosse encontrado, era adicionado ao final da lista. O endereço de armazenamento da variável, talvez recém-criado, foi então colocado na pilha de avaliação.

Desempenho

A gama de decisões de design que entravam na programação de um interpretador BASIC eram muitas vezes reveladas por meio de diferenças de desempenho.

As implementações de gerenciamento de linha frequentemente afetavam o desempenho e geralmente usavam a pesquisa linear . Delimitar cada linha com um CR faria um GOTO ou GOSUB para uma linha posterior levaria mais tempo, pois o programa precisaria repetir todas as linhas para encontrar o número da linha de destino. Em algumas implementações, como o Atari BASIC, o comprimento de cada linha era registrado e armazenado após o número da linha, para que o programa não tivesse que varrer cada caractere da linha para encontrar o próximo retorno de linha. Muitas implementações sempre procurariam por um número de linha para ramificar desde o início do programa; O MS-BASIC procuraria na linha atual, se o número da linha de destino fosse maior. Pittman adicionou um patch ao seu 6800 Tiny BASIC para usar uma pesquisa binária.

Trabalhar apenas com matemática inteira fornece outro grande impulso na velocidade. Como muitos benchmarks de computador da época eram pequenos e geralmente executavam matemática simples que não exigia ponto flutuante, o Integer BASIC superou a maioria dos outros BASICs. Em um dos primeiros benchmarks de microcomputadores conhecidos, os benchmarks Rugg/Feldman , o Integer BASIC foi duas vezes mais rápido que o Applesoft BASIC na mesma máquina. No Byte Sieve , onde a matemática era menos importante, mas o acesso à matriz e o desempenho do loop dominavam, o Integer BASIC levava 166 segundos, enquanto a Applesoft levava 200. Ele não apareceu no Creative Computing Benchmark , publicado pela primeira vez em 1983, quando o Integer BASIC não era mais fornecido por padrão. A série de testes a seguir, tirada de ambos os artigos originais de Rugg/Feldman, mostra o desempenho do Integer em relação ao BASIC derivado do MS na mesma plataforma.

Sistema CPU BÁSICO Teste 1 Teste 2 Teste 3 Teste 4 Teste 5 Teste 6 Teste 7
Apple II 6502 a 1 MHz Número inteiro BÁSICO 1.3 3.1 7.2 7.2 8.8 18.5 28,0
Apple II 6502 a 1 MHz Applesoft BASIC 1.3 8.5 16,0 17.8 19.1 28.6 44,8

Em teoria, o Atari BASIC deveria rodar mais rápido que os BASICs contemporâneos baseados no padrão da Microsoft. Como o código-fonte é totalmente tokenizado quando inserido, todas as etapas de tokenização e análise já estão concluídas. Mesmo operações matemáticas complexas estão prontas para serem executadas, com quaisquer constantes numéricas já convertidas em seu formato interno de 48 bits, e os valores das variáveis ​​são pesquisados ​​por endereço, em vez de terem que ser pesquisados. Apesar dessas vantagens teóricas, na prática, o Atari BASIC é mais lento do que outros BASICs de computadores domésticos , muitas vezes em grande quantidade. Na prática, isso não foi comprovado. Em dois benchmarks amplamente utilizados da época, o Sieve of Eratosthenes da revista Byte e o teste de benchmark Creative Computing escrito por David H. Ahl , o Atari terminou perto do final da lista em termos de desempenho, e foi muito mais lento que o contemporâneo Apple II . ou Commodore PET , apesar de ter a mesma CPU, mas executá-la com aproximadamente o dobro da velocidade de qualquer um. Terminou atrás de máquinas relativamente lentas como a Sinclair ZX81 e até mesmo de algumas calculadoras programáveis.

A maior parte da lentidão da linguagem decorreu de três problemas. A primeira é que as rotinas matemáticas de ponto flutuante foram mal otimizadas. No benchmark Ahl, uma única operação de expoente, que faz um loop interno sobre a função de multiplicação lenta, foi responsável por grande parte do mau desempenho da máquina. Em segundo lugar, a conversão entre o formato de ponto flutuante interno e os inteiros de 16 bits usados ​​em certas partes da linguagem era relativamente lenta. Internamente, esses números inteiros eram usados ​​para números de linha e indexação de matriz, juntamente com algumas outras tarefas, mas os números no programa tokenizado eram sempre armazenados no formato decimal codificado em binário (BCD). Sempre que um deles for encontrado, por exemplo, no número da linha em GOTO 100, o valor BCD tokenizado deve ser convertido em um número inteiro, uma operação que pode levar até 3.500 microssegundos. Outros BASICs evitaram esse atraso colocando maiúsculas e minúsculas na conversão de números que só poderiam ser inteiros, como o número da linha após um GOTO, mudando para o código especial ASCII para inteiro para melhorar o desempenho. O terceiro foi como o Atari BASIC implementou ramificações e FORloops. Para executar uma ramificação em um GOTOou GOSUB, o interpretador pesquisa em todo o programa o número da linha correspondente de que precisa. Uma pequena melhoria encontrada na maioria dos BASICs derivados da Microsoft é comparar o número da linha de destino com o número da linha atual e pesquisar a partir desse ponto se for maior ou começar do início se for menor. Essa melhoria estava faltando no Atari BASIC. Ao contrário de quase todos os outros BASICs, que empurrariam um ponteiro para o local do FORem uma pilha, então, quando chegasse ao ponto, NEXTpoderia facilmente retornar ao FORnovamente em uma única operação de ramificação, o Atari BASIC empurrou o número da linha. Isso significava que toda vez que a NEXTera encontrado, o sistema tinha que pesquisar em todo o programa para encontrar a FORlinha correspondente. Como resultado, quaisquer loops em um programa Atari BASIC causam uma grande perda de desempenho em relação a outros BASICs.

Veja também

Notas

Referências

Bibliografia

Leitura adicional

Código-fonte e documentos de design, em ordem cronológica do lançamento das implementações do BASIC: