Incorporar suas próprias funções diretamente via código-fonte com C++
Quando eu criei a linguagem de programação Ter/Terlang uma das coisas que eu queria que ela tivesse era justamente: a facilidade de poder hackear a linguagem e incorporar funções embutidas pelo programador.
Ou seja, você pode criar suas próprias funções nativas. Isso vai ser interessante quando eu começar a incorporar bibliotecas, principalmente de GameDev, como: SFML, SDL, Raylib e entre outras para ser utilizada pela Ter/Terlang.
Nesse exemplo vamos criar a função nativa: helloworld(), ou seja, ao imprimir essa função, deve exibir a mensagem: Hello, World!.
No momento se você criar um arquivo helloworld.ter e tentar fazer isso:
output(helloworld())
Após rodar: ter helloworld.ter, a saída será um erro:
[line 1] Error: Undefined variable: 'helloworld'.
Então, vamos modificar o código-fonte para que isso funcione!
Procedimento
Basta seguirmos 3 passos básicos para esse feito.
01. Antes de mais nada você precisa clonar
E entrar no projeto:
git clone https://github.com/terroo/terlang
cd terlang
02. Agora vamos editar o arquivo: ./src/Builtin.hpp
E adicionar ao final do arquivo o código abaixo:
class HelloWorld : public Callable {
public:
int arity() override;
std::any call(Interpreter &interpreter, std::vector<std::any> arguments) override;
std::string toString() override;
};
Todas as funções precisam herdar Callable de forma pública. As funções-membro: arity(), call() e toString() são o modelo para todas as funções que serão embutidas e precisam ser públicas.
03. Depois precisamos criar a execução para as funções-membro da classe HelloWorld que adicionamos.
Edite o arquivo ./src/Builtin.cpp e insira ao final do arquivo o conteúdo abaixo:
// ------ HelloWorld -----------
int HelloWorld::arity(){
return 0;
}
std::any HelloWorld::call(Interpreter &interpreter, std::vector<std::any> arguments){
if(arguments.size() > (size_t)arity() && interpreter.global != nullptr){
builtinError("helloworld");
}
std::string hello = "Hello, World!";
return std::any_cast<std::string>(hello);
}
std::string HelloWorld::toString(){
return "<function builtin>";
}
A função-membro
arity()precisa retornar a quantidade de argumentos que ela recebe, como a funçãohelloworld()não recebe nenhum argumento, retornamos zero, se fosse, por exemplo, uma função de nomeadd(x, y)recebe 2 argumentos, logo, precisaríamos retornarreturn 2;A função-membro
call()precisa sempre haver esseifinicial para verificar a quantidade de argumentos. Todos os retornos precisam ser transformados em std::any comstd::any_cast, como queremos que retorne umastringentão convertemos parastd::stringque será a frase que será exibida.E por final
toString()sempre deve possuir esse conteúdo para mapearmos o tipo de erro e saber que a falha na verdade é nesse tipo de função.
04. Adicionar helloworld ao mapa da Terlang
Agora vamos editar o arquivo: ./src/BuiltinFactory.cpp e adicionar AO FINAL DOS MAPAS builtinFactory e builtinNames o contexto. Com a sintaxe abaixo informe o nome da classe da sua função embutida, nesse caso: HelloWorld:
Lembre que na linha acima dela, precisa ADICIONAR UMA VÍRGULA:
,ao final da linha para mostrar que possuímos um novo elemento.
{typeid(std::shared_ptr<HelloWorld>), [](){ return std::make_shared<HelloWorld>(); }}
E fazer o mesmo em builtinNames, o primeiro elemento desse mapa é o nome que você deseja chamar no seu arquivo .ter, nesse caso chamamos ela de "helloworld" mesmo:
{"helloworld", typeid(std::shared_ptr<HelloWorld>)}
Tudo certo agora basta compilar e testar:
# rm -rf build/ se já tiver construído uma vez, pois o CMake pode usar o cache
cmake -B build .
cmake --build build
Crie o arquivo de teste: helloworld.ter:
auto hello = helloworld()
output(hello)
Nesse caso, fizemos diferente do arquivo acima, armazenamos o retorno de
helloworld()na variávelhello, mas você também pode imprimir diretamente caso queira:output(helloworld())
E rode:
./build/ter helloworld.ter
A saída será: Hello, World!
Se quiser que fique disponível para seu sistema é só instalar: sudo cmake --install build/.
Bem simples, né?! Esse procedimento está disponível na Wiki.
Para mais informações acesse o repositório: https://github.com/terroo/terlang/.
Aprenda a criar sua própria linguagem de programação com nosso Curso:
Top comments (0)