Categories
TeaScript

Release of TeaScript 0.9.0 🌻

TeaScript 0.9.0 was published on 02. Feb. 2023 and is available for download now. 🌞
☛☛☛ Download it here! ☚☚☚

TeaScript is available
as Host Application for Windows 10/11
as Host Application for Linux (Ubuntu 22.04) 🔥NEW🔥
as C++ Library 🔥NEW🔥

A snapshot of the TeaScript C++ Library is also available on Github. (But the download bundle here contains additional example script files.)

TeaScript is a Multi-Paradigm script language close to C++ syntax but easier to use.
Embed the TeaScript C++ Library in your Application with the easy to use and modern C++ API (header onlyno dependencies!) and extend your Application with anything needed dynamically during runtime!

Read more in this C++ scripting libraries comparison article: C++ Script Library Comparison.

More information about TeaScript and the most impressive highlights are available here:
Overview and Highlights of TeaScript

☛☛☛ Try and download TeaScript here! ☚☚☚

For the C++ audience now an excerpt of the Demo App code from the Library package for illustrating the TeaScript C++ API.

/*
 * SPDX-FileCopyrightText:  Copyright (c) 2023 Florian Thake <support |at| tea-age.solutions>. All rights reserved.
 * SPDX-License-Identifier: SEE LICENSE IN LICENSE.txt
 *
 * Licensed under the TeaScript Library Standard License. See LICENSE.txt or you may find a copy at
 * https://tea-age.solutions/teascript/product-variants/
 */

// TeaScript includes
#include "teascript/version.h"
#include "teascript/Engine.hpp"

//(std includes missing...)

// This test code will add some variables (mutable and const) to the script context
// and then execute script code, which will use them.
void test_code1()
{
    // create the TeaScript default engine.
    teascript::Engine  engine;

    // add 2 integer variables a and b.
    engine.AddVar( "a", 2 );   // variable a is mutable with value 2
    engine.AddVar( "b", 3 );   // variable b is mutable with value 3
    engine.AddConst( "hello", "Hello, World!" );    // variable hello is a const string.
    // For Bool exists different named methods because many types could be implicit converted to bool by accident.
    // like char * for example.
    engine.AddBoolVar( "speak", true );   // variable speak is a Bool with value true.
    

    // execute the script code passed as string. it computes new variable c based on values a and b.
    // also it will print the content of the hello variable.
    // finally it returns the value of variable c.
    auto const res = engine.ExecuteCode(    "const c := a + b\n"
                                            "if( speak ) {\n"
                                            "    println( hello )\n"
                                            "}\n"
                                            "c\n" 
                                        );
    // print the result.
    std::cout << "c is " << res.GetAsInteger() << std::endl;
}


// this is our simple callback function which we will call from TeaScript code.
// The callback function signature is always ValueObject (*)( Context & )
teascript::ValueObject user_callback( teascript::Context &rContext )
{
    // look up variable 'some_var'
    auto const val = rContext.FindValueObject( "some_var" );

    // print a message and the value of 'some_var'
    std::cout << "Hello from user_callback! some_var = " << val.PrintValue() << std::endl;

    // return 'nothing' aka NaV (Not A Value).
    return {};
}

// This test code will register a C++ callback function and then executes a script
// which will call it.
void test_code2()
{
    // create the TeaScript default engine.
    teascript::Engine  engine;

    // register a function as a callback. can use arbitrary names.
    engine.RegisterUserCallback( "call_me", user_callback );

    // execute the script which will create variable 'some_var' and then call our callback function.
    engine.ExecuteCode( "const some_var := \"Hello!\"\n"
                        "if( is_defined call_me and call_me is Function ) { // safety checks! \n"
                        "    call_me( )\n"
                        "}\n"                 
                      );
}


// This is another callback function.
// It will create the sum of 2 passed parameters and return the result to the script.
teascript::ValueObject calc_sum( teascript::Context &rContext )
{
    if( rContext.CurrentParamCount() != 2 ) { // this check could be relaxed also...
        // in case of wrong parameter count, throw eval error with current source code location.
        throw teascript::exception::eval_error( rContext.GetCurrentSourceLocation(), "Calling calc_sum: Wrong amount of parameters! Expecting 2.");
    }

    // get the 2 operands for the calculation.
    auto const lhs = rContext.ConsumeParam();
    auto const rhs = rContext.ConsumeParam();

    // calculate the sum and return result as ValueObject.
    return teascript::ValueObject( lhs.GetAsInteger() + rhs.GetAsInteger() );
}

// This test code will register a callback function and call it from a script with parameters.
void test_code3()
{
    // create the TeaScript default engine.
    teascript::Engine  engine;

    // register a function as a callback. can use arbitrary names.
    engine.RegisterUserCallback( "sum", calc_sum );

    // execute the script which will call our function
    auto const res = engine.ExecuteCode( "sum( 1234, 4321 )\n" );

    // print the result.
    std::cout << "res is " << res.GetAsInteger() << std::endl;
}


// This test code demonstrates how arbitrary user data can be transferred into function callbacks.
void test_code4()
{
    // assume this is our important application/business context...
    struct MyUserContext
    {
        unsigned int magic_number = 0xcafecafe;
    } mycontext;

    // a capturing lambda is one way, using std::bind another....
    auto lambda = [&]( teascript::Context & /*rContext*/ ) -> teascript::ValueObject {
        // here we have access to all captured variables. So, we can use our context and have access to all members.
        return teascript::ValueObject( static_cast<teascript::Integer>( mycontext.magic_number ) );
    };

    // create the TeaScript default engine.
    teascript::Engine  engine;

    // register the lambda as callback. can use arbitrary names.
    engine.RegisterUserCallback( "getmagic", lambda );

    // execute the script which will call our function
    auto const res = engine.ExecuteCode( "getmagic()\n" );

    // print the result.
    std::cout << "res is " << std::hex << res.GetAsInteger() << std::endl;
}


// Executes a TeaScript file and returns its result. 
// This function has a very basic feature set. The TeaScript Host Application has more capabilities.
// Beside other features it also comes with an interactive shell, REPL, debug options and time measurement.
// The TeaScript Host Application can be downloaded for free here: https://tea-age.solutions/downloads/
int exec_script_file( std::vector<std::string> &args )
{
    args.erase( args.begin() );  // we don't need the program name
    std::string const filename = args.front(); // copy script filename
    args.erase( args.begin() );  // ... and remove it. the script args are left over (if any)

    std::filesystem::path const script( std::filesystem::absolute( teascript::util::utf8_path( filename ) ) );

    // create the TeaScript default engine.
    teascript::Engine  engine;

    try {
        // and execute the script file.
        auto const res = engine.ExecuteScript( script, args );

        // does the script end via any exit( code ) ?
        if( engine.HasExitCode() ) {
            std::cout << "script exit code: " << engine.GetExitCode() << std::endl;
            return static_cast<int>(engine.GetExitCode());
        } else if( res.HasPrintableValue() ) { // does it return a printable result?
            std::cout << "result: " << res.PrintValue() << std::endl;
        }
    } catch( teascript::exception::runtime_error const &ex ) {
        teascript::util::pretty_print( ex );
        return EXIT_FAILURE;
    } catch( std::exception const &ex ) {
        std::cout << "Exception: " << ex.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

Leave a Reply

Your email address will not be published. Required fields are marked *