Running Decision from C

Warning

If you are embedding into a C++ program, it is very, very recommended that when you include a C header file, you encapsulate it with an extern block, like so:

extern "C" {
    #include <decision.h>
    #include <dsheet.h>
}

Decision Strings

Loading Decision Strings

To load a string with Decision source code in into a Sheet, use:

Sheet *d_load_string(const char *source, const char *name, CompileOptions *options)

Take Decision source code and compile it into bytecode, but do not run it.

Return

A malloc’d sheet containing all of the compilation info.

Parameters
  • source: The source code to compile.

  • name: The name of the sheet. If NULL, it is set to "source".

  • options: A set of compile options. If NULL, the default settings are used.

You can then run any compiled Sheet with:

bool d_run_sheet(struct _sheet *sheet)

Run the code in a given sheet, given that it has gone through d_codegen_compile, and it has exactly one defined Start function.

Return

If the sheet ran without any errors.

Parameters
  • sheet: The sheet to run.

#include <decision.h>
#include <dsheet.h>

int main() {
    // Load the string.
    Sheet *sheet = d_load_string("Start~#1 ; Print(#1, 'Hello, world!')", NULL, NULL);

    // Run the sheet.
    d_run_sheet(sheet);

    // Free the sheet from memory.
    d_sheet_free(sheet);

    return 0;
}

Note

For safety, you can check to see whether a sheet has failed to compile (usually because there was an error in the code) by checking to see if sheet->hasErrors is true.

If a sheet does have an error, d_run_sheet will not run it.

Running Decision Strings

To run a Decision source code string directly, use:

bool d_run_string(const char *source, const char *name, CompileOptions *options)

Take Decision source code and compile it into bytecode. If it compiled successfully, run it in the virtual machine.

Return

If the code compiled/ran without any errors.

Parameters
  • source: The source code the compile.

  • name: The name of the sheet. If NULL, it is set to "source".

  • options: A set of compile options. If NULL, the default settings are used.

#include <decision.h>

int main() {
    // Run the string.
    d_run_string("Start~#1 ; Print(#1, 'Hello, world!')", NULL, NULL);

    return 0;
}

Decision Files

Loading Decision Files

To load a Decision file from the disk into a Sheet, use:

Sheet *d_load_file(const char *filePath, CompileOptions *options)

Take a Decision file, decide whether it is a source or an object file based on its contents, and load it into memory.

Return

A malloc’d sheet object containing all of the compilation info.

Parameters
  • filePath: The file path of the file to load.

  • options: A set of compile options. If NULL, the default settings are used.

#include <decision.h>
#include <dsheet.h>

int main() {
    // Load the sheet into memory.
    Sheet *sheet = d_load_file("hello_world.dc", NULL);

    // Run the sheet.
    d_run_sheet(sheet);

    // Free the sheet from memory.
    d_sheet_free(sheet);

    return 0;
}

Running Decision Files

To run a Decision file directly, use:

bool d_run_file(const char *filePath, CompileOptions *options)

Take a Decision file, decide whether it is a source or an object file based on its contents, and run it in the virtual machine.

Return

If the code compiled/ran without any errors.

Parameters
  • filePath: The file path of the file to load.

  • options: A set of compile options. If NULL, the default settings are used.

#include <decision.h>

int main() {
    // Run the file.
    d_run_file("hello_world.dc", NULL);

    return 0;
}

Decision Functions

In order to run specific functions and subroutines, you first need to know how to pass arguments and get return values from them.

Passing Arguments

To pass arguments to a function or subroutine, you need to push the values onto the Decision Virtual Machine’s stack in the correct order. This can be done with the following functions:

void d_vm_push(DVM *vm, dint value)

Push an integer value onto the stack.

Parameters
  • vm: The VM whose stack to push onto.

  • value: The value to push onto the stack.

void d_vm_push_float(DVM *vm, dfloat value)

Push a float value onto the stack.

Parameters
  • vm: The VM whose stack to push onto.

  • value: The value to push onto the stack.

void d_vm_push_ptr(DVM *vm, void *ptr)

Push a pointer onto the stack.

Parameters
  • vm: The VM whose stack to push onto.

  • ptr: The pointer to push onto the stack.

Getting Return Values

To get return values from a function or subroutine, you need to pop the values from the Decision Virtual Machine’s stack in reverse order. This can be done with the following functions:

dint d_vm_pop(DVM *vm)

Pop an integer from the top of the stack.

Return

The integer at the top of the stack.

Parameters
  • vm: The VM whose stack to pop from.

dfloat d_vm_pop_float(DVM *vm)

Pop a float from the top of the stack.

Return

The float at the top of the stack.

Parameters
  • vm: The VM whose stack to pop from.

void *d_vm_pop_ptr(DVM *vm)

Pop a pointer from the top of the stack.

Return

The pointer at the top of the stack.

Parameters
  • vm: The VM whose stack to pop from.

Calling Decision Functions

Finally, you can call the function or subroutine itself using:

bool d_run_function(struct _DVM *vm, struct _sheet *sheet, const char *funcName)

Run the specified function/subroutine in a given sheet, given the sheet has gone through d_codegen_compile.

Return

If the function/subroutine ran without any errors.

Parameters
  • vm: The VM to run the function on. The reason it is a seperate argument is because it allows you to push and pop arguments and return values seperately.

  • sheet: The sheet the function lives in.

  • funcName: The name of the function/subroutine to run.

> decision.dc

[Function(IsEven)]
[FunctionInput(IsEven, Integer)]
[FunctionOutput(IsEven, Boolean)]

Define(IsEven)~#1
Mod(#1, 2)~#2
Equal(#2, 0)~#3
Return(IsEven, #3)

[Subroutine(SayHi)]

Define(SayHi)~#10
Print(#10, "Hi! :3")
// main.c
#include <dcfg.h>
#include <decision.h>
#include <dsheet.h>
#include <dvm.h>

#include <stdio.h>

int main() {
    // Load the sheet into memory.
    Sheet *sheet = d_load_file("decision.dc", NULL);

    // Create a Decision Virtual Machine.
    DVM vm = d_vm_create();

    // Calling a function/subroutine with no inputs or outputs is easy:
    d_run_function(&vm, sheet, "SayHi");

    // It's good practice to reset the VM once you've run something.
    d_vm_reset(&vm);

    dint value = 531780;

    // To call the IsEven function, we first need to push the argument onto
    // the stack.
    d_vm_push(&vm, value);

    // REMEMBER: If you have more than one argument, push the arguments IN
    // THE CORRECT ORDER.

    // Then call the function:
    d_run_function(&vm, sheet, "IsEven");

    // Then pop the return values out IN REVERSE ORDER.
    dint isEven = d_vm_pop(&vm);

    // dcfg.h has some handy macros for when you want to print dint or
    // dfloat types:
    if (isEven) {
        printf("%" DINT_PRINTF_d " is even!\n", value);
    } else {
        printf("%" DINT_PRINTF_d " is odd!\n", value);
    }

    // Free the VM.
    d_vm_free(&vm);

    d_sheet_free(sheet);
    return 0;
}