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 definedStart
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. IfNULL
, 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;
}