Sistema de Scripts, UGDK e seus módulos

Ae gente, com as ultimas mudanças que foram pushadas hoje no repositório, o sistema de scripts da ugdk tá pronto. :smiley:
Ok vai, talvez não exatamente pronto, é capaz que no futuro alteremos algo, ou arrumemos algum bug, mas já tá usável já. hehehe
E também já testamos ele no Windows e funciona (algo que demoramos pra fazer), só falta testar no Mac.

Agora o propósito mor desse tópico não é falar exatamente do Sistema de Script (tem muita coisa pra falar ai, provavelmente eu e o Wil faremos isso depois)…
O propósito aqui é falar dos “módulos” da UGDK, que para os desavisados, são (aproximadamente) os namespaces de C++ contidos na UGDK, exportados (pelo SWIG, parte do sistema) para as linguagens de script que estão implementadas no sistema (por enquanto Lua e Python).

Os módulos são definidos nos arquivos <>.i na pasta src/modules. Eles são basicamente headers de C/C++ com algumas macros a mais do SWIG.
O importante aqui é que eles incluem os headers da UGDK (por exemplo, graphic.i inclui os headers de src/ugdk/graphic), afinal de contas eles exportam as coisas de C++ da UGDK para os scripts, eles tem que conhecer as coisas né :stuck_out_tongue:
Então, como você já deve ter pensado agora, QUALQUER MUDANÇA NA UGDK PODE ACARRETAR MUDANÇAS NOS MÓDULOS. Fazer os módulos em suma é fácil, mas ficar revendo toda vez que tem algum commit na UGDK as mudanças que tem pra atualizar os módulos é muito chato, então sem mais delongas: o propósito desse tópico é exatamente falar disso, para que quem mexa na UGDK possa atualizar os módulos por si próprio ou ao menos AVISAR (somehow, talvez até aqui) o que mudaram para que alguém atualize os módulos.

Agora, não é exatamente “qualquer mudança” na UGDK… Mais precisamente, aqui vai a lista das coisas que, se feitas, implicam ter que atualizar os módulos (ou criar novos):

[ul][li]Alterações nos Headers: [list]
[li]Novos headers -> novos módulos ou adicionar os novos headers no módulo existente adequado.[/li]
[li]Novas classes ou outros tipos -> setar ela pra ser export_class no módulo (exceto se for class template), e lembrem-se: nada de nested struct/union.[/li]
[/list][/li]

[li]Alterações na Interface (novos métodos, alterando método existente, e tal): [list]
[li]Se método retornar um objeto novo (sempre ou com possibilidade de ser null), de forma que ele passa a “ownership” do objeto pra quem lhe chamou, tem que setar o método como %newobject[/li]
[li]Se método rouba a ownership de algum objeto que ele recebe como argumento, IN CONSTRUCTION LOL[/li]
[li]Se nome (classe/método) é para ser ignorado (não exportá-lo), usar a macro %ignore (isso pode ser usado para não exportar coisas especificas, como métodos que recebem tipos que não são exportados para a linguagem de script)[/li]
[li]Se nome (classe/método) conflita com outro (por exemplo, overload… SWIG não gosta de nomes conflitantes), %rename pode ser usado para renomear um dos nome em conflito para outro nome durante a exportação.[/li]
[li]Coisas que recebem especializações de templates: como o SWIG não exporta templates, as vezes é necessário que você especialize o template no módulo como um novo tipo usando a macro %template[/li]
[li]Usando coisas da STD (std::map, std::string, e outras): SWIG tem arquivos <>.i “libs” para cuidar da exportação de tipos assim. Se coisas da STD passam a ser usadas, você terá que usar %include <> (onde <> são nomes como “std_string.i”, “std_map.i”, etc)[/li]
[li]Usando coisas de outras partes da UGDK: use %import para importá-las para o módulo em questão. Dê preferência a importar headers (melhor ainda se for headers de forward declaration, como o ugdk/graphic.h) passando a opção ‘module’ especificando o nome do módulo em que o tipo se encontra, se o tipo que você busca foi exportado em outro módulo.[/li]
[/list][/li][/ul]

Eu sei que essa é uma descrição bem “simples” para algo que não é, mas é mais para dar a visão geral para vocês.
Todas essas coisas que falei já são usadas de uma forma ou de outra nos módulos existentes na UGDK agora, então são bons exemplos. Eles também foram todos feitos seguindo um mesmo padrão, note isso :stuck_out_tongue:
E nos arquivos <>.i, A ORDEM DAS COISAS FAZ DIFERENÇA! Por exemplo, se uma classe que você está exportando usa um tipo que foi exportado em outro módulo, você tem que dar o %import do outro módulo ANTES de incluir essa classe. Assim como %rename, %ignore, %newobject devem ser feitos antes das coisas em questão.

De qualquer jeito, eu e o Wil estamos sempre por ai para esclarecer outras dúvidas.

And that’s all folks! (i think :P)

Omar explicou bem. Notem que vocês não precisam manjar TUDO do swig pra contribuir com o módulos. Como o Omar disse, contanto que vocês identifiquem as alterações que caem nessas categorias, e avisem de alguma maneira o quanto antes, já estarão ajudando bastante.

A parte da explicação que está incompleta se deve ao fato de não existir uma ferramenta pronto no SWIG pra tratar esses casos. Ou seja, ainda precisamos fazê-las nós mesmos. Assim que estiverem prontas, atualizamos aqui. Até lá, pode ser que usar o sistema de script acarrete um certo vazamento de memória XD [size=3pt]ou algo um pouco pior…[/size]

Vocês precisam pensar bem em algum modo de simplificar isso, ou ao menos diminuir a possibilidade de erros/esquecimentos.

Ainda estou com a impressão de que esse sistema de scripts trouxe muitas complicações adicionais. Configurar o ambiente de desenvolvimento está ainda mais difícil e demorado, e também existem mais preocupações no desenvolvimento da UGDK.
Algumas destas coisas precisam ser automatizadas, e tudo precisa estar bem documentado e com tutoriais.

E uma pergunta meio off-topic: vocês já incluíram o código fonte do Lua neste sistema de scripts?

Infelizmente, o SWIG exige que tenhamos que fazer tudo isso. Talvez dê para automatizar, mas do mesmo jeito teria que haver um jeito de “marcar” as funções que caem em casos especias, como o %newobject. Para isso precisaríamos implementar um parser de C++ e, bem, isso é bastante difícil.

Mas de fato, o sitema de script adiciona à complexidade de compilação. A ideia é que isso compense removendo a complexidade de desenvolvimento dos projetos, de maneira que os eventuais usuários não precisem recorrer à uma recompilação deles. Se não conseguirmos isso, então teremos miseravelmente.

Sobre documentar, esse tópico é justamente pra isso =P. Obviamente, ele é apenas um esboço, mas o grosso da coisa tá aí. Assim que tivermos tempo podemos colocar mais detalhadamente na Wiki.

Por fim, não, ainda não coloquei o código do Lua na UGDK. Se der, faço isso no sprint que começa amnhã, embora ache que outras metas com maior prioridade já estejam no backlog.

Sim, eu sei que automatizar tudo realmente é complicado, mas seria bom listar de forma mais detalhada as operações que podem ou não ser automatizadas. A idéia é mais lembrar o desenvolvedor do que ele precisa fazer, e ajudá-lo no processo.

Um parser para automatizar isso não precisaria entender tudo de C++, mas apenas detectar algumas coisas. Talvez até dê para automatizar alguns itens com expressões regulares :stuck_out_tongue:

Humm…

O maior problema de fazer o parser é que C/C++ tem umas sintaxes bem obscuras que não são normalmente usadas. Mesmo se limitarmos à sintaxe apenas das declarações. Mas não seja por isso, se você acha que rola, Jeff, então podemos tentar. Vai ser divertido fazer uns Autômatos ae XD.

Só não sei quando teremos tempo de fazer isso >.<

Mudei um negócio no post original, sobre os %import.
Antes nos <>.i usávamos %import <module/nome>, mas como quase todo módulo da ugdk precisa de 1 tipo ou outro de algum outro módulo, quase todo módulo tinha um import para outro módulo.
Isso tava dando uma dependencia cíclica dos infernos… Que magicamente só dava merda no Windows O_o
Anyway, descobri que o jeito certo é fazer o seguinte (e eu já alterei os módulos pra seguirem isso):
%import(modulo=“nome”) <ugdk/whatever.h>
e em vários lugares, simplesmente usando o header de forward declaration daquele módulo da UGDK (como o ugdk/graphic.h) funciona.

Quanto à discussão, Jeff, vc tá certo em relação a simplificar isso :stuck_out_tongue:
Mas como o Wil disse, isso não é simples. Sim dá pra fazer sem problemas, mas acreditamos ser mais importante realmente testar o sistema antes, senão as simplificações para outras pessoas usarem e tal não terão muito sentido, e por isso que agora tamo mais focado em fazer o Asteroids, pra testar.

O Sistema já tá usável, mas não tá pronto ainda sabe :stuck_out_tongue: É um Beta, digamos hahaha