Incorporate your own functions directly via source code with C++
When I created the Ter/Terlang programming language one of the things I wanted it to have was precisely: the ease of being able to hack the language and incorporate functions built in by the programmer.
In other words, you can create your own native functions. This will be interesting when I start incorporating libraries, mainly from GameDev, such as: SFML, SDL, Raylib and others to be used by Ter/Terlang.
In this example, we will create the native function: helloworld()
, that is, when printing this function, it should display the message: Hello, World!.
Right now if you create a helloworld.ter
file and try to do this:
output(helloworld())
After running: ter helloworld.ter
, the output will be an error:
[line 1] Error: Undefined variable: 'helloworld'.
So, let's modify the source code to make this work!
Procedure
We just need to follow 3 basic steps to do this.
01. First of all, you need to clone
And enter the project:
git clone https://github.com/terroo/terlang
cd terlang
02. Now let's edit the file: ./src/Builtin.hpp
And add the code below to the end of the file:
class HelloWorld : public Callable {
public:
int arity() override;
std::any call(Interpreter &interpreter, std::vector<std::any> arguments) override;
std::string toString() override;
};
All functions need to inherit Callable
in a public form. The member functions: arity()
, call()
and toString()
are the template for all functions that will be built in and need to be public.
03. Next, we need to create the execution for the member functions of the HelloWorld
class that we added.
Edit the file ./src/Builtin.cpp
and insert the following content at the end of the file:
// ------ 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>";
}
The member function
arity()
needs to return the number of arguments it receives. Since the functionhelloworld()
does not receive any arguments, we return zero. If it were, for example, a function namedadd(x, y)
that receives 2 arguments, we would need to returnreturn 2;
The member function
call()
always needs to have this initialif
to check the number of arguments. All returns need to be transformed into std::any withstd::any_cast
. Since we want it to return astring
, we convert it tostd::string
, which will be the sentence that will be displayed.And finally
toString()
must always have this content so that we can map the error type and know that the failure is actually in this type of function.
04. Add helloworld
to the Terlang map
Now let's edit the file: ./src/BuiltinFactory.cpp
and add the context AT THE END OF THE MAPS builtinFactory
and builtinNames
. With the syntax below, inform the name of the class of your built-in function, in this case: HelloWorld
:
Remember that in the line above it, you need to ADD A COMMA:
,
at the end of the line to show that we have a new element.
{typeid(std::shared_ptr<HelloWorld>), [](){ return std::make_shared<HelloWorld>(); }}
And do the same in builtinNames
, the first element of this map is the name you want to call in your .ter
file, in this case we call it "helloworld"
:
{"helloworld", typeid(std::shared_ptr<HelloWorld>)}
All right now just compile and test:
# rm -rf build/ if you have already built it once, because CMake can use the cache
cmake -B build . cmake --build build
Create the test file: helloworld.ter
:
auto hello = helloworld()
output(hello)
In this case, we did it differently from the file above, we stored the return of
helloworld()
in the variablehello
, but you can also print it directly if you want:output(helloworld())
And run:
./build/ter helloworld.ter
The output will be: Hello, World!
If you want it to be available for your system, just install it: sudo cmake --install build/
.
Pretty simple, right?! This procedure is available on the Wiki.
For more information, access the repository: https://github.com/terroo/terlang/.
Learn how to create your own programming language with our Course:
Top comments (0)