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 esseif
inicial para verificar a quantidade de argumentos. Todos os retornos precisam ser transformados em std::any comstd::any_cast
, como queremos que retorne umastring
então convertemos parastd::string
que 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)