-
Notifications
You must be signed in to change notification settings - Fork 1
Wiki Terlang(dev mode)
This wiki is for those who want to hack Ter/Terlang and implement their own implementations in the language.
Assuming you are going to add a new built-in function named: helloworld()
that when called in the script displays the message: Hello, World!
in the terminal.
- Create a new class in the file:
./terlang/src/Builtin.hpp
Add the class (with initials in capital letters) and inherit publicly from
Callable
and add the member functions as shown in the example below.
class HelloWorld : public Callable {
public:
int arity() override;
std::any call(Interpreter &interpreter, std::vector<std::any> arguments) override;
std::string toString() override;
};
- Now create the execution in
./terlang/src/Builtin.cpp
In
arity()
return the number of arguments that your function needs to receive, in the case ofhelloworld()
there are no arguments, therefore,return 0
:
// ------ 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("exec");
}
std::string hello = "Hello, World!";
return std::any_cast<std::string>(hello); }
std::string HelloWorld::toString(){
return "<function builtin>";
}
Put the logic in
call()
and always return withstd::any_cast
, if there is no return, return empty, example:return std::any_cast<std::string>(std::string{});
. The other information follows the pattern of this example.
- Now in the file:
./terlang/src/Interpreter.cpp
add to the constructor of the classInterpreter::Interpreter()
as a string the name you want to call inscript.ter
and define the type for the class you created:
// At the end of all that are already defined
global->define("helloworld", std::shared_ptr<HelloWorld>{});
- And finally, when executing the member function:
std::any Interpreter::visitCallExpr(std::shared_ptr<Call> expr)
create a newelse if
block before the finalelse
, the call:
...
}else if(callee.type() == typeid(std::shared_ptr<HelloWorld>)){ // Builtin
auto builtin = std::make_shared<HelloWorld>();
return builtin->call(*this, arguments);
}else{
...
Recompile and test with the generated binary.
After creating a test file, e.g. main.ter
, add this:
auto hello = helloworld()
output(hello)
And run: ter helloworld.ter
you should see the phrase: Hello, World!
.