Clipper++

Aqui é o lugar para bater papo e trocar idéias sobre os mais variados assuntos

Moderador: Moderadores

Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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... )
Imagem
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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
Imagem
Avatar do usuário
Itamar M. Lins Jr.
Administrador
Administrador
Mensagens: 7928
Registrado em: 30 Mai 2007 11:31
Localização: Ilheus Bahia
Curtiu: 1 vez

Clipper++

Mensagem 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.
Saudações,
Itamar M. Lins Jr.
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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...
Imagem
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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
Imagem
Avatar do usuário
Nascimento
Usuário Nível 4
Usuário Nível 4
Mensagens: 763
Registrado em: 19 Jul 2008 12:11
Localização: OLINDA-PE

Clipper++

Mensagem 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?
A arte de programar é simplesmente fazer seus pensamentos serem interpretados por uma maquina :) clipper 5.3 /harbour/minigui
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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....
Imagem
Avatar do usuário
Nascimento
Usuário Nível 4
Usuário Nível 4
Mensagens: 763
Registrado em: 19 Jul 2008 12:11
Localização: OLINDA-PE

Clipper++

Mensagem 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
A arte de programar é simplesmente fazer seus pensamentos serem interpretados por uma maquina :) clipper 5.3 /harbour/minigui
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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...
Imagem
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Clipper++

Mensagem 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
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Clipper++

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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... :/
Imagem
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Clipper++

Mensagem 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.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
carlosro
Usuário Nível 1
Usuário Nível 1
Mensagens: 5
Registrado em: 30 Dez 2019 09:03
Localização: Curitiba

Clipper++

Mensagem 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 ?
Avatar do usuário
bencz
Usuário Nível 4
Usuário Nível 4
Mensagens: 524
Registrado em: 28 Abr 2012 17:36
Contato:

Clipper++

Mensagem 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.
Imagem
Responder