Răsfoiți Sursa

Examples for beginners (#169)

* Add examples folder

* Draft change

* Add draft changes

* Add examples

* Refactor examples

---------

Co-authored-by: Mahbub Alam <alam.mahbub214@gmail.com>
Mahbub Alam 2 ani în urmă
părinte
comite
6f8bf82e9a

+ 35 - 0
examples/1_type_cast.cpp

@@ -0,0 +1,35 @@
+
+/**
+ * This example demonstrates the type casting feature of PocketPy.
+ * It creates a virtual machine and cast PyObject* to different types.
+*/
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    PyObject* str_obj = py_var(vm, "hello world");
+    // Cast PyObject* to Str type
+    Str& str = py_cast<Str&>(vm, str_obj); 
+    std::cout << "string: " << str.c_str() << std::endl; // hello world
+
+
+    PyObject* int_obj = py_var(vm, 10);
+    // Cast PyObject* to Int type
+    int int_var = py_cast<int>(vm, int_obj);
+    std::cout << "int: " << int_var << std::endl; // 10
+
+    PyObject* float_obj = py_var(vm, 10.5);
+    // Cast PyObject* to double type
+    double float_var = py_cast<double>(vm, float_obj);
+    std::cout << "float: " << float_var << std::endl; // 10.5
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}

+ 36 - 0
examples/2_module_and_binding.cpp

@@ -0,0 +1,36 @@
+
+/**
+ * This example demonstrate the process of creating a python module and
+ * bind a function to it, as well as the procedure for calling the function.
+*/
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    // Create a module
+    PyObject* math_module = vm->new_module("math");
+
+    // Bind a function named "add" to the module
+    vm->bind(math_module, "add(a: int, b: int) -> int",
+        [](VM* vm, ArgsView args){
+            int a = py_cast<int>(vm, args[0]);
+            int b = py_cast<int>(vm, args[1]);
+            return py_var(vm, a + b);
+        });
+        
+  
+    // Call the "add" function
+    PyObject* f_sum = math_module->attr("add");
+    PyObject* result = vm->call(f_sum, py_var(vm, 4), py_var(vm, 5));
+    std::cout << "Sum: " << py_cast<int>(vm, result) << std::endl;   // 9
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}

+ 50 - 0
examples/3_list_operation.cpp

@@ -0,0 +1,50 @@
+
+/**
+ * This example demonstrates how to build a List object and how to access its elements.
+ * It creates a python module named "math_utils" and bind a function named "average" to it.
+ * It exercises creating a List and accessing its elements.
+ * It also demonstrates how to cast a python object to a C++ type.
+*/
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    // Create a module
+    PyObject* math_utils = vm->new_module("math_utils");
+
+    // Bind a function named "average" to the module
+    vm->bind(math_utils, "average(l: List[float]) -> float",
+        [](VM* vm, ArgsView args){
+            // Cast the argument to a list
+            List& l = py_cast<List&>(vm, args[0]);
+            double sum = 0;
+
+            // Calculate the sum of the list by iterating through the list
+            for(auto& e : l){
+                sum += py_cast<double>(vm, e);
+            }
+            return py_var(vm, sum / l.size());
+        });
+
+    // Create a list of numbers and covert it to a python object
+    List numbers;
+    numbers.push_back(py_var(vm, 1.0));
+    numbers.push_back(py_var(vm, 2.0));
+    numbers.push_back(py_var(vm, 3.0));
+    PyObject* list = py_var(vm, std::move(numbers));
+
+    // Call the "average" function
+    PyObject* f_average = math_utils->attr("average");
+    PyObject* result = vm->call(f_average, list);
+    std::cout << "Average: " << py_cast<double>(vm, result) << std::endl;   // 2
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}

+ 108 - 0
examples/4_dictionary_operation.cpp

@@ -0,0 +1,108 @@
+
+/**
+ * This example illustrate use of Dict in PocketPy.
+ * It creates a python module named "employee" and bind four functions to it.
+ * It exercises setting and getting elements in a Dict.
+*/
+
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    // Create "employee" module
+    PyObject* employee_module = vm->new_module("employee");
+
+    // Bind a function named "get_first_name" to the module
+    vm->bind(employee_module, "get_first_name(employee: Dict) -> str",
+        "Returns first_name of the employee",  // docstring
+        [](VM* vm, ArgsView args){
+            // Cast the argument to a dictionary
+            Dict& employee = CAST(Dict&, args[0]);
+            // Access the first_name field and return it
+            return employee.try_get(VAR("first_name"));
+        });
+
+    // Bind a function named "get_last_name" to the module
+    vm->bind(employee_module, "get_last_name(employee: Dict) -> str",
+        "Returns last_name of the employee",  // docstring
+        [](VM* vm, ArgsView args){
+            // Cast the argument to a dictionary
+            Dict& employee = CAST(Dict&, args[0]);
+            // Access the last_name field and return it
+            return employee.try_get(VAR("last_name"));
+        });
+
+    // Bind a function named "get_salary" to the module
+    // It accepts a dictionary as argument and returns a float
+    vm->bind(employee_module, "get_salary(employee: Dict) -> float",
+        "Returns salary of the employee",  // docstring
+        [](VM* vm, ArgsView args){
+            // Cast the argument to a dictionary
+            Dict& employee = CAST(Dict&, args[0]);
+            // Access the salary field and return it
+            return employee.try_get(VAR("salary"));
+        });
+
+    // Bind a function named "love_coding" to the module
+    // It accepts a dictionary as argument and returns a bool
+    vm->bind(employee_module, "love_coding(employee: Dict) -> bool",
+        "Returns Yes if the employee loves coding, No otherwise",  // docstring
+        [](VM* vm, ArgsView args){
+            // Cast the argument to a dictionary
+            Dict& employee = CAST(Dict&, args[0]);
+
+            // Access the hobbies field and cast it to a list
+            List& hobbies = CAST(List&, employee.try_get(VAR("hobbies")));
+
+            // Iterate through the list and check if the employee loves coding
+            for(auto& e : hobbies){
+                if(CAST(Str&, e) == Str("Coding")){
+                    return VAR("Yes");
+                }
+            }
+            return VAR("No");
+        });
+
+    // Create employee dictionary covert it to a python object
+    Dict employee(vm);
+    employee.set(VAR("first_name"), VAR("John"));
+    employee.set(VAR("last_name"), VAR("Doe"));
+    employee.set(VAR("age"), VAR(30));
+    employee.set(VAR("salary"), VAR(10000.0));
+    List hobbies;
+    hobbies.push_back(VAR("Reading"));
+    hobbies.push_back(VAR("Walking"));
+    hobbies.push_back(VAR("Coding"));
+    employee.set(VAR("hobbies"), VAR(std::move(hobbies)));
+    PyObject* employee_obj = VAR(std::move(employee));
+
+    // Call the "get_first_name" function
+    PyObject* f_get_first_name = employee_module->attr("get_first_name");
+    PyObject* first_name = vm->call(f_get_first_name, employee_obj);
+    std::cout << "First name: " << CAST(Str&, first_name) << std::endl;   // First name: John
+
+    // Call the "get_last_name" function
+    PyObject* f_get_last_name = employee_module->attr("get_last_name");
+    PyObject* last_name = vm->call(f_get_last_name, employee_obj);
+    std::cout << "Last name: " << CAST(Str&, last_name) << std::endl;   // Last name: Doe
+ 
+    // Call the "get_salary" function
+    PyObject* f_get_salary = employee_module->attr("get_salary");
+    PyObject* salary = vm->call(f_get_salary, employee_obj);
+    std::cout << "Salary: "<< CAST(double, salary) << std::endl;   // Salary: 10000
+
+    // Call the "love_coding" function
+    PyObject* f_love_coding = employee_module->attr("love_coding");
+    PyObject* love_coding = vm->call(f_love_coding, employee_obj);
+    std::cout << "Loves coding: " << CAST(Str&, love_coding) << std::endl;   // Loves coding: Yes
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}

+ 26 - 0
examples/5_python_scripting.cpp

@@ -0,0 +1,26 @@
+
+/**
+ * This example demonstrate the use of PocketPy as a scripting language.
+ * It creates a virtual machine and execute a python script.
+*/
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    // Print "hello world" to the console
+    vm->exec("print('hello world')"); // hello world
+
+    // List comprehension
+    vm->exec("l = [i*i for i in range(1, 6)]");
+    vm->exec("print(l)"); // [1, 4, 9, 16, 25]
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}

+ 87 - 0
examples/6_type_checker.cpp

@@ -0,0 +1,87 @@
+
+/**
+ * This example demonstrates how to create different types of objects and
+ * how to check their types.
+*/
+
+#include "pocketpy.h"
+
+using namespace pkpy;
+
+
+int main(){
+    // Create a virtual machine
+    VM* vm = new VM();
+
+    // Create a module
+    PyObject* type_checker = vm->new_module("type_checker");
+
+    // Bind a function named "get_type" to the module
+    vm->bind(type_checker, "get_type(obj: object) -> str",
+        "Returns type of a python object",  // docstring
+        [](VM* vm, ArgsView args){
+            PyObject* obj = args[0];
+            if(is_type(obj, vm->tp_int)){
+                return py_var(vm, "int");
+            }
+            else if(is_type(obj, vm->tp_str)){
+                return py_var(vm, "str");
+            }
+            else if(is_type(obj, vm->tp_float)){
+                return py_var(vm, "float");
+            }
+            else if(is_type(obj, vm->tp_bool)){
+                return py_var(vm, "bool");
+            }
+            else if(is_type(obj, vm->tp_dict)){
+                return py_var(vm, "dict");
+            }
+            else if(is_type(obj, vm->tp_list)){
+                return py_var(vm, "list");
+            }
+            else if(is_type(obj, vm->tp_tuple)){
+                return py_var(vm, "tuple");
+            }
+            else{
+                return py_var(vm, "unknown");
+            }
+        });
+    
+    // Get the "get_type" function
+    PyObject* f_get_type = type_checker->attr("get_type");
+
+    // Create a dictionary
+    Dict d(vm);
+    d.set(py_var(vm, "key"), py_var(vm, "value"));
+
+    // Create a list
+    List l;
+    l.push_back(py_var(vm, "list_element"));
+
+    // Declare a two-element tuple
+    Tuple t(2);
+    t[0] = py_var(vm, "tuple_element_0");
+    t[1] = py_var(vm, "tuple_element_1");
+
+    // Create different types of objects
+    PyObject* int_obj = py_var(vm, 1);
+    PyObject* str_obj = py_var(vm, "hello");
+    PyObject* float_obj = py_var(vm, 1.0);
+    PyObject* bool_obj = py_var(vm, true);
+    PyObject* dict_obj = py_var(vm, std::move(d));
+    PyObject* list_obj = py_var(vm, std::move(l));
+    PyObject* tuple_obj = py_var(vm, std::move(t));
+
+    // Call the "get_type" function and print type of different objects
+    std::cout << "Type of 1: " << CAST(Str&, vm->call(f_get_type, int_obj)) << std::endl;
+    std::cout << "Type of \"hello\": " << CAST(Str&, vm->call(f_get_type, str_obj)) << std::endl;
+    std::cout << "Type of 1.0: " << CAST(Str&, vm->call(f_get_type, float_obj)) << std::endl;
+    std::cout << "Type of true: " << CAST(Str&, vm->call(f_get_type, bool_obj)) << std::endl;
+    std::cout << "Type of {\"key\": \"value\" }: " << CAST(Str&, vm->call(f_get_type, dict_obj)) << std::endl;
+    std::cout << "Type of [\"list_element\"]: " << CAST(Str&, vm->call(f_get_type, list_obj)) << std::endl;
+    std::cout << "Type of (\"tuple_element_0\", \"tuple_element_1\"): " << CAST(Str&, vm->call(f_get_type, tuple_obj)) << std::endl;
+
+    // Dispose the virtual machine
+    delete vm;
+    return 0;
+}