Página 1 de 1

Clipper++

Enviado: 29 Dez 2019 18:50
por bencz
Bons Dias a todos!

Decidi por abrir algumas informações sobre um projeto que iniciei a alguns anos atrás... que ficou bastante tempo parado e agora estou dando uma olhada nele novamente, esse projeto denominei ele de Clipper++, que é um estudo que iniciei sobre o dev. de compiladores... depois de obter muito conhecimento no desenvolvimento de compiladores, como com o meu projto, Zinnia Language, decidi iniciar a implementação da minha versão do CA-Clipper, com a ideia de ser compativel com CA-Clipper 5.3b.
Bom, esse projeto tem algumas diferenças bastante fortes, comparado com o funcionamento do Clipper / Harbour / xBase++ e seus derivados, a grande diferença é que o meu compilador gera código nativo de maquina, diferente do CA-Clipper/Harbour e etc, que gera um código C com todos os P-Codes dentro de um array, que é interpretado em tempo de execução.

Outra diferença é que o Clipper++ surgiu com a ideia ja da orientação a objetos, mesmo o que é considerado função no Clipper, como QOUT, na verdade é um metodo dentro da classe STD da runtime da linguagem, um pequeno exemplo da classe STD:

Código: Selecionar todos

*****************************************************************************
*** Arquivo CONSOLE.PRG
*****************************************************************************
PARTIAL CLASS CLPSTD
PRIVATE:
    STATIC METHOD COUT(__STRING STR)

PUBLIC:
    STATIC METHOD QOUT(...)
ENDCLASS

STATIC METHOD COUT(__STRING STR) CLASS CLPSTD
    LOCAL __INT32 NPRTCHR := 0
    LOCAL __STRING TMPSTR := ""
    
    IF STR == NIL
        TMPSTR := "NIL"
    ENDIF
    
    NPRTCHR := EXTERNAL("msvcrt.dll", "printf", "%s", TMPSTR)
RETURN NPRTCHR

STATIC METHOD QOUT(...) CLASS CLPSTD
    LOCAL __INT32 NARGS := 0
    LOCAL __ARRAY AARGS := {}
    
    NARGS := ARGCOUNT()
    IF NARGS <= 0
        CLPSTD:COUT("")
        RETURN NIL
    ELSE
        CLPSTD:COUT(CLPSTD:CRLF)
    ENDIF
    
    FOR I := 0 TO NARGS
        IF I > 0
            CLPSTD:COUT(" ")
        ENDIF
        
        CLPSTD:COUT(AARGS[I])
    NEXT
RETURN NIL
Claro, que isso é um pequeno exemplo, existem diversas outras coisas ja implementadas, mas, após verificar muitas coisas, decidi por alterar muitas coisas na runtime, como o acesso a funções externas, no caso, atualmente é utilizando o "keyword" __EXTERNAL, a tipagem das variáveis são necessárias apenas para a chamada de funções externas, definidas em DLLs, que existem a tipagem correta.
Devido a natureza do compilador, não é necessário ficar mixando código C com xBase, pois, o compilador compila o código xBase diretamente para nível de maquina, portanto, toda a runtime do compilador é escrito na propria linguagem do compilador...

Atualmente, o compilador ainda é closed source, mas, assim que terminar algumas modificações, irei liberar o código fonte no seguinte repositório, ( https://github.com/bencz/ClipperPlusPlus ).

Segue um pequeno exemplo de um código que o compilador já é capaz de compilar e executar com sucesso:

Código: Selecionar todos

PROCEDURE MAIN()
  LOCAL ASTRUCT1 := {  { "CODIGO", "C",  3, 0 },  { "NOME"  , "C", 30, 0 }}

  DBCREATE( "CLIENTES", ASTRUCT1 )

  dbUseArea( .T.,, "CLIENTES",, if(.F. .OR. .F., !.F., NIL), .F.,, )
  dbCreateIndex( "CLI1", "CODIGO", {|| CODIGO}, if( .F., .T., NIL ) )

  CLIENTES->( DBAPPEND() )
  _FIELD->CODIGO := "001" ; _FIELD->NOME := "ALEXANDRE BENCZ"
  CLIENTES->( DBAPPEND() )
  _FIELD->CODIGO := "002" ; _FIELD->NOME := "RICARDO BENCZ"
  CLIENTES->( DBAPPEND() )
  _FIELD->CODIGO := "003" ; _FIELD->NOME := "CARLOS BENCZ"

  dbGoTop()
  while !EOF()
    QOut( CLIENTES->CODIGO, CLIENTES->NOME )
    dbSkip(1)
  ENDDO

  dbCloseAll()
  dbSelectArea( "1" )

  FERASE("CLIENTES.DBF")
  FERASE("CLI1.NTX")
RETURN NIL
Esse mesmo código, usando os padrões do xBase ( que tem um monte de coisas que são convertidas no pré-processamento.. ), fica igual ao seguinte código:

Código: Selecionar todos

PROCEDURE MAIN()
  LOCAL ASTRUCT1 := { ;
           { "CODIGO", "C",  3, 0 }, ;
           { "NOME"  , "C", 30, 0 }}  

  DBCREATE( "CLIENTES", ASTRUCT1 )
  
  USE CLIENTES NEW
  INDEX ON CODIGO TO CLI1
  
  CLIENTES->( DBAPPEND() )
  REPLACE CODIGO WITH "001", NOME WITH "ALEXANDRE BENCZ"
  CLIENTES->( DBAPPEND() )
  REPLACE CODIGO WITH "002", NOME WITH "RICARDO BENCZ"
  CLIENTES->( DBAPPEND() )
  REPLACE CODIGO WITH "003", NOME WITH "CARLOS BENCZ"
  
  GO TOP
  DO WHILE !EOF()
    ? CLIENTES->CODIGO, CLIENTES->NOME
    SKIP
  ENDDO
  
  CLOSE ALL
  FERASE("CLIENTES.DBF")
  FERASE("CLI1.NTX")
RETURN NIL
Tenho planos para implementar o pré-processador... mas, isso fica para outros tempos...., um dia implemento o carinha

Enfim, vale ressaltar aqui que esse é um projeto de estudos...., esse projeto não tem o intuito de ser um produto comercial, ou seja eu não irei cobrar para utilizar ele ou qualquer coisa parecida...
Por este motivo, o projeto é 100% open-source e regido sob a licença do LGPL v3 ( podendo ser alterada a qualquer momento, para uma licença mais rígida, caso seja necessário... )

Clipper++

Enviado: 29 Dez 2019 19:13
por bencz
Segue uma pequena amostra, na diferença de tempo de execução de um simples 'Ola mundo', entre um executável gerado pelo Harbour contra um gerado pelo meu compilador:

Harbour:
ptime main_harbour.exe

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== main_harbour.exe ===

Ola mundo
Execution time: 0.549 s
Clipper++
ptime Template.exe

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== Template.exe ===
OLa mundo

Execution time: 0.257 s

Clipper++

Enviado: 29 Dez 2019 20:21
por Itamar M. Lins Jr.
Ola!
O Eric Lendvai, e outros estão criando uma fundação (entidade) para o Harbour.
Já tem até doação de dinheiro e hospedagem.
Com esse conhecimento não poderia ser o Capitão do Harbour 3.2 ?
Seria bom as outras pessoas com conhecimentos avançados se posicionarem a respeito lá no forum internacional. Agora com remuneração e outras metas.

Saudações,
Itamar M. Lins Jr.

Clipper++

Enviado: 30 Dez 2019 03:19
por bencz
Eu estava dando uma estudada na documentação do pré-processador do CA-Clipper e do Harbour... é um desafio bastante interessante...
Vamos tomar como exemplo, o seguinte comando de pré-processamento:

Código: Selecionar todos

#command USE <(db)> [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ;
            [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ;
            [CODEPAGE <cp>] [INDEX <(index1)> [, <(indexN)>]] ;
            [ TABLE <cTable> ] ;
            [ <dbEngine: ACCESS, MYSQL, ORACLE, INFORMIX, SQL, FIREBIRD> ];
            [ FROM <cServer> ] ;
            [ QUERY <cQuery> ] ;
            [ USER <cUser> PASSWORD <cPassword> ]=> ;
         [ HB_AdoSetTable( <cTable> ) ; ] ;
         [ HB_AdoSetEngine( <(dbEngine)> ) ; ] ;
         [ HB_AdoSetServer( <cServer> ) ; ] ;
         [ HB_AdoSetQuery( <cQuery> ) ; ] ;
         [ HB_AdoSetUser( <cUser> ); HB_AdoSetPassword( <cPassword> ) ; ] ;
         dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ;
                    if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.> [, <cp>] ) ;
         [; dbSetIndex( <(index1)> )] ;
         [; dbSetIndex( <(indexN)> )]
Fazer o parse do código,não é algo tão complicado... o problema entra na analise dos 'opcionais', que são os itens que estão entre '[' & ']'.
No código, é possivel ter varios "#command" que iniciei em USE <(db)>, mas, na hora de fazer o pré processamento, é necessário identificar qual é o USE <(db)> correto...
Existe também o USE <(db)> do standart do CA-Clipper / xHarbour, que é o seguinte:

Código: Selecionar todos

#command USE <(db)> [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ;
            [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ;
            [CODEPAGE <cp>] [CONNECTION <nConn>] [INDEX <(index1)> [, <(indexN)>]] => ;
         dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ;
                    if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.>,  [<cp>], [<nConn>] ) ;
         [; dbSetIndex( <(index1)> )] ;
         [; dbSetIndex( <(indexN)> )]
No momento, tenho uma ideia de qual seria a melhor maneira para fazer a escolha do comando correto, durante o pré-processamento, mas, tenho la minhas duvidas se realmente vai funcionar, só implementando para testar... posso dar uma lida no fonte do preprocessador do (x)Harbour ou do clip-itk para ver como eles resolveram isso...

Clipper++

Enviado: 30 Dez 2019 03:40
por bencz
Um outro ponto... a primeira palavra do #command, pode já ser um 'marker', por exemplo:

Código: Selecionar todos

#command <(db)> USE  [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ;
            [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ;
            [CODEPAGE <cp>] [CONNECTION <nConn>] [INDEX <(index1)> [, <(indexN)>]] => ;
         dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ;
                    if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.>,  [<cp>], [<nConn>] ) ;
         [; dbSetIndex( <(index1)> )] ;
         [; dbSetIndex( <(indexN)> )]

***  Então, para usar esse comando, seria utilizado a seguinte linha de código:
CLIENTES USE NEW
Outro ponto que torna o préprocessador um grande desafio... a ordem dos comandos opcionais pode ser conforme o gosto do programador...
Por exemplo:

Código: Selecionar todos

** Esse comando é valido, segundo o #command original do std do CA-Clipper
USE CLIENTES NEW INDEX CLI

** Esse é o mesmo comando apresentado acima... e também é valido segundo o #command original do STD do CA-Clipper
USE CLIENTES INDEX CLI NEW

Clipper++

Enviado: 03 Jan 2020 23:09
por Nascimento
gostei muito quando vc falou e mudar de pcode para codigos direto de maquina, me bateu a curiosidade no harbour não daria para fazer essa maravilhosa modificação?

Clipper++

Enviado: 06 Jan 2020 07:24
por bencz
Nascimento, bom dia!
Então, eu cheguei a pensar em fazer isso com o Harbour, mas, a única parte aproveitável do código seria o analisador sintático e semântico... o resto, seria todo jogado no lixo..., devido a natureza do compilador e do funcionamento, existe uma rigidez muito grande na estrutura, com a utilização dos p-codes do CA-Clipper....
Então, acabei optando por implementar o meu proprio compilador... que agora, estou quebrando a cabeça com o pré-processador....

Clipper++

Enviado: 06 Jan 2020 10:08
por Nascimento
entendo, até porque se o harbour abandona-se o Pcode seria maravilhoso ficaria em pé de igualdade aos mais conhecidos como delphi, C, C++ e pascal
onde o codigo é rodado direto e não em uma VM, acho que quando estavam construindo o harbour faltou essa ideia, compatibilizar com o clipper, mais mudar essa parte

Clipper++

Enviado: 06 Jan 2020 10:30
por bencz
Pois é... o grande problema de código nativo, é quanto aos macros, variaveis 100% dinamicas....

Por exemplo, em nivel de maquina isso aqui não é possivel, de forma trivial:

Código: Selecionar todos

LOCAL oVariavel := 10

? oVariavel

oVariavel := "string"

? oVariavel

oVariavel := {}
Uma alternativa que tentei, é algo semelhante a isso, em nivel em C:

Código: Selecionar todos

#include <stdio.h>

int main()
{
    int _tmpVar_0 = 10;
    const char* _tmpVar_1 = "string";
    void* p;
    
    p = &_tmpVar_0;
    printf("%d\n", *(int*)p);
    
    p = _tmpVar_1;
    printf("%s\n", (const char*)p);
    
    return 0;
}
na linguagem que criei, baseada em C# e Python, eu implementei um sistema de Reflection, mas, não implementei para funções locais... somente para obter nome de metodo, parametros, alterar valor de variavel global e etc...
Então, o que tenho funcionando que é algo proximo ao macro ( & ) do CA-Clipper, ta meio longe de funcionar de forma correta...
Uma coisa q eu poderia fazer, é simplesmente ignorar os operadores macro, e não implementar eles no compilador...

Clipper++

Enviado: 06 Jan 2020 10:51
por sygecom
Lembro que no harbour.exe tem o seguinte parâmetro: /gc que pode ser:

/gc[<type>] output type: C source (.c) (default)
<type>: 0=compact 1=normal 2=verbose (default)
3=generate real C code

Eu nunca nem testei para ver como gera compilando com -gc3

Clipper++

Enviado: 06 Jan 2020 10:58
por JoséQuintas
Talvez em 1986 fosse interessante código de máquina.

Precisa velocidade pra que?
pra enviar um comando entre cliente/servidor?
pra trafegar informação pela rede?
pra navegar entre campos da tela?
Que diferença vai fazer?

Acho que já passou a época disso.

Talvez se fosse pra hardware dedicado, e não pra computador, mas até isso vém mudando.

Clipper++

Enviado: 06 Jan 2020 14:42
por bencz
José, boa tarde!
A minha ideia não é criar um produto viável em nível de mercado ou algo inovador ou qualquer coisa do tipo... esse é um projeto de estudos e nada mais.... e nesse meu estudo, tenho como meta implementar uma linguagem que seja compatível ( minimamente ) com CA-Clipper, mas, gerando código em nivel de maquina, nada mais... (:

@sygecom, mesmo utilizando essa opção, existe a abstração para a vm do Harbour... :/

Clipper++

Enviado: 06 Jan 2020 15:11
por JoséQuintas
bencz escreveu:José, boa tarde!
A minha ideia não é criar um produto viável em nível de mercado ou algo inovador ou qualquer coisa do tipo... esse é um projeto de estudos e nada mais.... e nesse meu estudo, tenho como meta implementar uma linguagem que seja compatível ( minimamente ) com CA-Clipper, mas, gerando código em nivel de maquina, nada mais... (:
@sygecom, mesmo utilizando essa opção, existe a abstração para a vm do Harbour... :/
Não tem nada a ver, mas tem a ver, o seguinte:

Como estou migrando pra MySQL.
Primeiro gravei duplicado e agora estou ajustando aos poucos, começando da função mais interna, pra retirar dependências da externa.

No meu caso tem lá a função a() que chama b(), que chama c() que chama d(), que chama e(), e trabalham com o registro posicionado.
Estou ajustando primeiro as funções e() que dependem do posicionamento de d().
Depois as d() que dependem do que vém de c()
E assim por diante.

O que tem a ver?
E se partir do Harbour, e tentar fazer no mesmo estilo?
Provavelmente tem coisas que dependem da VM do Harbour e tem coisas que não.
TALVEZ seja possível ir retirando dependências da VM aos poucos, até não sobrar nada.

Clipper++

Enviado: 23 Jan 2020 10:34
por carlosro
@Bencz

Muito interessante!!
Pelo que li, atualmente funciona somente no Windows, correto ?
Você tem algum plano para migrar o compilador para gerar arquivos ELF também, e compatibilizar com distribuições Debian ou Suse ?
Algum plano para implementar o gerador de código para ppc64le ?

Clipper++

Enviado: 23 Jan 2020 12:58
por bencz
Carlosro, boas tardes!!

Correto, atualmente funciona somente no Windows...
Eu tenho planos de migrar o gerador de código para gerar código LLVM, e deixar portavel para as N arquiteturas suportadas pelo LLVM... e tambem, implementar a runtime tanto para windows quanto para linux.