agentsclimarketplace

Bif development

Skill ortus-boxlang/skills/boxlang-core-development/bif-development

Use this skill when creating custom BoxLang built-in functions (BIFs): @BoxBIF annotation, invoke() method, argument handling, accessing BoxRuntime and services, BoxLang vs Java BIF implementations, member functions, and registering BIFs via modules.From its SKILL.md

Install
npx -y skills add ortus-boxlang/skills --skill bif-development

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.7 KB, ~2.2k tokens by cl100k_base, as published. Nobody here has run it

BoxLang BIF Development

Overview

Built-in functions (BIFs) are globally available functions in BoxLang — no imports needed. When placed in a module's bifs/ directory, they are automatically discovered and registered at module load time. BIFs can be implemented in either BoxLang or Java.

BoxLang BIF

Minimal Example

// bifs/Greet.bx
// File name = function name (case-insensitive: greet, Greet, GREET all work)

@BoxBIF
class {

    function invoke( required string name ) {
        return "Hello, #arguments.name#!"
    }

}
// Usage anywhere in BoxLang (no import)
greet( "Ada" )   // "Hello, Ada!"

Full-Featured BoxLang BIF

// bifs/StringTitleCase.bx
@BoxBIF
class {

    /**
     * Converts a string to title case.
     *
     * @str The input string
     * @delimiters Word delimiters (default: space)
     * @return Title-cased string
     */
    string function invoke(
        required string str,
        string delimiters = " "
    ) {
        if ( !len( arguments.str ) ) return ""

        var words = listToArray( arguments.str, arguments.delimiters )
        return words
            .map( (w) -> uCase( left(w,1) ) & lCase( mid(w,2,len(w)) ) )
            .toList( arguments.delimiters )
    }

}

Java BIF

For performance-critical functions or when you need deep JVM access:

// src/main/java/com/example/bifs/StringTitleCase.java
package com.example.bifs;

import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
import ortus.boxlang.runtime.bifs.BoxMember;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;

@BoxBIF
// Optional: also register as a member function on String
@BoxMember( type = BoxLangType.STRING, name = "titleCase" )
public class StringTitleCase extends BIF {

    // Declare argument metadata
    public StringTitleCase() {
        super();
        declaredArguments = new Argument[] {
            new Argument( true,  "string", Key.of( "str" ) ),
            new Argument( false, "string", Key.of( "delimiters" ), " " )
        };
    }

    /**
     * @param context   Current execution context
     * @param arguments Function arguments scope
     */
    @Override
    public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
        String str        = arguments.getAsString( Key.of( "str" ) );
        String delimiters = arguments.getAsString( Key.of( "delimiters" ) );

        if ( str == null || str.isEmpty() ) return "";

        String[] words = str.split( "[" + delimiters + "]" );
        StringBuilder sb = new StringBuilder();
        for ( int i = 0; i < words.length; i++ ) {
            if ( i > 0 ) sb.append( delimiters.charAt( 0 ) );
            if ( !words[i].isEmpty() ) {
                sb.append( Character.toUpperCase( words[i].charAt(0) ) );
                sb.append( words[i].substring(1).toLowerCase() );
            }
        }
        return sb.toString();
    }
}

With @BoxMember, the BIF is also callable as a member function:

"hello world".titleCase()  // "Hello World"
titleCase( "hello world" ) // "Hello World" (BIF style)

Key Java Classes for BIF Development

Class/InterfacePackagePurpose
BIFortus.boxlang.runtime.bifsBase class for all BIFs
@BoxBIFortus.boxlang.runtime.bifsMarks a class as a BIF
@BoxMemberortus.boxlang.runtime.bifsRegisters as member function
IBoxContextortus.boxlang.runtime.contextCurrent execution context
ArgumentsScopeortus.boxlang.runtime.scopesTyped argument access
Keyortus.boxlang.runtime.scopesString key interning
Argumentortus.boxlang.runtime.typesArgument descriptor
BoxLangTypeortus.boxlang.runtime.typesEnum of BoxLang types
BoxRuntimeortus.boxlang.runtimeRuntime singleton

Accessing BoxRuntime Services From a BIF

import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.cache.providers.ICacheProvider;
import ortus.boxlang.runtime.services.CacheService;

@BoxBIF
public class CachedFetch extends BIF {

    private BoxRuntime runtime = BoxRuntime.getInstance();

    @Override
    public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
        String url = arguments.getAsString( Key.of( "url" ) );

        CacheService cacheService = runtime.getCacheService();
        ICacheProvider cache      = cacheService.getDefaultCache();

        Object cached = cache.get( Key.of( url ) );
        if ( cached != null ) return cached;

        // Fetch data...
        Object result = fetchFromUrl( url );
        cache.set( Key.of( url ), result, 300L, 0L );  // 300s TTL
        return result;
    }
}

Accessing Context Services

@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
    // Get the current request scope
    IScope requestScope = context.getScopeNearby( RequestScope.name );

    // Get the application scope
    IScope appScope = context.getScopeNearby( ApplicationScope.name );

    // Get the session scope
    IScope sessionScope = context.getScopeNearby( SessionScope.name );

    // Resolve a variable
    Object val = context.scopeFindNearby( Key.of( "myVar" ), null ).value();

    // Invoke another function
    Object result = context.invokeFunction( Key.of( "len" ), new Object[]{ "hello" } );

    return result;
}

BoxLang BIF with Runtime Access

// bifs/GetAppSetting.bx
@BoxBIF
class {

    function invoke( required string key, any defaultValue = "" ) {
        // Access the BoxRuntime
        var runtime  = boxRuntime
        var appScope = getApplicationScope()  // available in web context

        return appScope.keyExists( arguments.key )
            ? appScope[ arguments.key ]
            : arguments.defaultValue
    }

}

Registering a BIF Alias

// Register under multiple names via multiple @BoxBIF annotations
@BoxBIF
@BoxBIF( alias = "strTitleCase" )
@BoxBIF( alias = "toTitleCase" )
public class StringTitleCase extends BIF { ... }

Member Function Registration

Member functions are BIFs callable on a specific type using dot notation:

@BoxBIF
@BoxMember( type = BoxLangType.ARRAY,  name = "shuffle" )   // array.shuffle()
@BoxMember( type = BoxLangType.STRING, name = "toSlug" )    // str.toSlug()
@BoxMember( type = BoxLangType.STRUCT, name = "deepMerge" ) // struct.deepMerge()
public class MyBIF extends BIF { ... }
[3,1,2].shuffle()
"Hello World".toSlug()   // "hello-world"
config.deepMerge( overrides )

BIF Argument Types

// Argument types available in ortus.boxlang.runtime.types.Argument
new Argument( required, type, key )
new Argument( required, type, key, defaultValue )

// Types: "any", "string", "numeric", "boolean", "array", "struct",
//        "query", "date", "function", "closure", "lambda", "class"

Testing Your BIF

// tests/specs/MyBIFTest.bx
class extends="testbox.system.BaseSpec" {

    function run() {
        describe( "greet BIF", function() {

            it( "should greet a person by name", function() {
                expect( greet("Ada") ).toBe( "Hello, Ada!" )
            })

            it( "should handle empty name", function() {
                expect( greet("") ).toBe( "Hello, !" )
            })

            it( "should be callable as member function", function() {
                expect( "Ada".titleCase() ).toBe( "Ada" )
                expect( "hello world".titleCase() ).toBe( "Hello World" )
            })

        })
    }

}
box testbox run

Discovering Registered BIFs

// List all registered BIFs (including your custom ones)
writeDump( getFunctionList() )

// Check if a specific BIF exists
if ( structKeyExists( getFunctionList(), "greet" ) ) {
    writeOutput( "greet BIF is registered!" )
}

References

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.