Importing libraries
This commit is contained in:
33
README.md
33
README.md
@@ -83,8 +83,41 @@ main = func {
|
||||
}
|
||||
```
|
||||
|
||||
Or this:
|
||||
|
||||
```
|
||||
main func {
|
||||
dingus(dingus)
|
||||
}
|
||||
|
||||
dingus func {
|
||||
arg0(arg0)
|
||||
}
|
||||
```
|
||||
|
||||
<sub>functions are indeed objects >:)</sub>
|
||||
|
||||
Funk supports importing other libraries written in Funk (FFI libraries will come soon). Use the import function to import those libraries.
|
||||
|
||||
Ensure that the library you are importing is in the directory pointed to by the `FUNK_HOME` environment variable.
|
||||
|
||||
```
|
||||
// myCoolLibrary.funk
|
||||
importedFunction func {
|
||||
println("The imported function has been called")
|
||||
}
|
||||
|
||||
importedValue = "Hi there from the library!"
|
||||
|
||||
// main.funk
|
||||
import("myCoolLibrary")
|
||||
|
||||
main func {
|
||||
myCoolLibrary::importedFunction()
|
||||
println(myCoolLibrary::importedValue)
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Funk is licensed to you under the GNU GPL v3.0. Contributions are welcome!
|
||||
|
||||
5
libs/myLib.funk
Normal file
5
libs/myLib.funk
Normal file
@@ -0,0 +1,5 @@
|
||||
dingle func {
|
||||
println("this func is dingling")
|
||||
}
|
||||
|
||||
someConstant = "heheheha"
|
||||
@@ -1,15 +1,21 @@
|
||||
#include "runner.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
#include "../parser/parser.h"
|
||||
#include "../lexer/lexer.h"
|
||||
|
||||
Object::Object(ASTValue value) : value(value) {}
|
||||
Object::Object(ASTFunction function) : value(function) {}
|
||||
Object::Object() = default;
|
||||
|
||||
std::map<std::string, Object> Executor::getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
std::map<std::string, Object> globalVariables;
|
||||
|
||||
std::optional<ASTNode> Executor::consume() {
|
||||
if (iterator < code.nodes.size()) {
|
||||
@@ -121,7 +127,52 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
||||
|
||||
}
|
||||
if (fnName == "import") {
|
||||
// work on importing modules later
|
||||
for (Object &object : callArgs) {
|
||||
ASTValue arg;
|
||||
if (object.isCustomObject == false && std::holds_alternative<ASTValue>(object.value)) {
|
||||
arg = std::get<ASTValue>(object.value);
|
||||
if (arg.type == ValueType::String) {
|
||||
std::optional<std::string> importName = arg.getString();
|
||||
if (importName.has_value()) {
|
||||
const char* libpathEnv = std::getenv("FUNK_PATH");
|
||||
if (libpathEnv == nullptr) {
|
||||
std::cout << "Error: FUNK_PATH environment variable is not set" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::string libpath = libpathEnv;
|
||||
// Import the Funk file for this library
|
||||
std::ifstream file(libpath + "/" + importName.value() + ".funk");
|
||||
// Execute the file and capture it's content
|
||||
if (file.is_open()) {
|
||||
std::string fc;
|
||||
std::string buf;
|
||||
while (std::getline(file, buf)) {
|
||||
fc += buf + "\n";
|
||||
}
|
||||
Executor importedCode(ASTCodeBlock(Lexer(fc).content));
|
||||
for (auto const &[key, val] : importedCode.getVariables()) {
|
||||
std::string newVarName = importName.value() + "::" + key;
|
||||
if (isInitCall) {
|
||||
globalVariables[newVarName] = val;
|
||||
variables[newVarName] = val;
|
||||
} else {
|
||||
variables[newVarName] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "Type mismatch - expecting a string but found something else" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
std::cout << "Type mismatch - expecting string for import" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
std::cout << "Type mismatch - expecting string for import" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (isInitCall) {
|
||||
@@ -268,14 +319,14 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
||||
if (variables.find(fnName) != variables.end()) {
|
||||
if (variables[fnName].isCustomObject) {
|
||||
if (std::holds_alternative<ASTFunction>(variables[fnName].children["handler"])) {
|
||||
Executor(std::get<ASTFunction>(variables[fnName].children["handler"]).body, false, {}, callArgs);
|
||||
Executor(std::get<ASTFunction>(variables[fnName].children["handler"]).body, false, globalVariables, callArgs);
|
||||
} else {
|
||||
std::cout << "Object " << fnName << " does not have a handler function" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (std::holds_alternative<ASTFunction>(variables[fnName].value)) {
|
||||
Executor(std::get<ASTFunction>(variables[fnName].value).body, false, {}, callArgs);
|
||||
Executor(std::get<ASTFunction>(variables[fnName].value).body, false, globalVariables, callArgs);
|
||||
|
||||
}
|
||||
} else {
|
||||
@@ -289,6 +340,7 @@ Executor::Executor(ASTCodeBlock in, bool isInitCall, std::map<std::string, Objec
|
||||
}
|
||||
}
|
||||
if (isInitCall) {
|
||||
Executor(std::get<ASTFunction>(variables[std::string("main")].value).body, false, variables);
|
||||
globalVariables = variables;
|
||||
Executor(std::get<ASTFunction>(variables[std::string("main")].value).body, false, globalVariables);
|
||||
}
|
||||
}
|
||||
@@ -37,5 +37,6 @@ class Executor {
|
||||
std::optional<ASTNode> peek(int ahead = 1);
|
||||
public:
|
||||
explicit Executor(ASTCodeBlock in, bool isInitCall = false, std::map<std::string, Object> scopeVals = {}, std::vector<Object> args = {});
|
||||
std::map<std::string, Object> getVariables();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import("myLib")
|
||||
|
||||
dingus func {
|
||||
// println is an inbuilt function, you can also use print
|
||||
println("you got dingused")
|
||||
@@ -16,6 +18,9 @@ dingus func {
|
||||
println(3.14)
|
||||
println("I am a string!")
|
||||
println(true)
|
||||
// access things from a library
|
||||
println(myLib::someConstant)
|
||||
myLib::dingle()
|
||||
}
|
||||
|
||||
// main is the entry point of the program, like many other languages
|
||||
|
||||
Reference in New Issue
Block a user