stuff
This commit is contained in:
@@ -425,6 +425,8 @@ struct _Ground {
|
|||||||
} Log;
|
} Log;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
void (*save) (GroundBytecode* bytecode, const char* path);
|
||||||
|
GroundBytecode (*load) (const char* path);
|
||||||
struct {
|
struct {
|
||||||
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
|
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
|
||||||
void (*optimise) (GroundBytecodeProgram* program);
|
void (*optimise) (GroundBytecodeProgram* program);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ sources = files(
|
|||||||
|
|
||||||
'src/Bytecode/Heap/get.c',
|
'src/Bytecode/Heap/get.c',
|
||||||
'src/Bytecode/Heap/set.c',
|
'src/Bytecode/Heap/set.c',
|
||||||
|
'src/Bytecode/save.c',
|
||||||
|
'src/Bytecode/load.c',
|
||||||
'src/Bytecode/Instruction/execute.c',
|
'src/Bytecode/Instruction/execute.c',
|
||||||
'src/Bytecode/Program/execute.c',
|
'src/Bytecode/Program/execute.c',
|
||||||
'src/Bytecode/Program/optimise.c',
|
'src/Bytecode/Program/optimise.c',
|
||||||
@@ -99,6 +101,10 @@ sources = files(
|
|||||||
'src/Struct/addField.c'
|
'src/Struct/addField.c'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cli_sources = files(
|
||||||
|
'src/cli/main.c'
|
||||||
|
)
|
||||||
|
|
||||||
incdir = include_directories('include')
|
incdir = include_directories('include')
|
||||||
|
|
||||||
libffi = dependency('libffi', version : '>=3.0.0')
|
libffi = dependency('libffi', version : '>=3.0.0')
|
||||||
@@ -112,3 +118,5 @@ pkg.generate(lib,
|
|||||||
version : meson.project_version(),
|
version : meson.project_version(),
|
||||||
description : 'Ground virtual machine',
|
description : 'Ground virtual machine',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cli = executable('ground', cli_sources, include_directories : incdir, install : true, link_with : lib)
|
||||||
|
|||||||
@@ -24,10 +24,14 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
|
|||||||
goto *jumpTable[instruction->type];
|
goto *jumpTable[instruction->type];
|
||||||
|
|
||||||
IF: {
|
IF: {
|
||||||
|
GroundValue* cond = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
if (cond->as.Bool) {
|
||||||
|
return instruction->args.at[1];
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
JUMP: {
|
JUMP: {
|
||||||
return -1;
|
return instruction->args.at[0];
|
||||||
}
|
}
|
||||||
END: {
|
END: {
|
||||||
return -2;
|
return -2;
|
||||||
|
|||||||
141
src/Bytecode/load.c
Normal file
141
src/Bytecode/load.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
#include "../../include/ground.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static GroundValue readValue(FILE* f) {
|
||||||
|
GroundValue v = {0};
|
||||||
|
uint8_t tag;
|
||||||
|
if (fread(&tag, 1, 1, f) != 1) {
|
||||||
|
Ground.Log.Error("failed to read value type in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tag) {
|
||||||
|
case 0: {
|
||||||
|
v.type.type = GroundType_Int;
|
||||||
|
fread(&v.as.Int, 8, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
v.type.type = GroundType_Double;
|
||||||
|
fread(&v.as.Double, 8, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
v.type.type = GroundType_Char;
|
||||||
|
fread(&v.as.Char, 1, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
v.type.type = GroundType_Bool;
|
||||||
|
fread(&v.as.Bool, 1, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
v.type.type = GroundType_String;
|
||||||
|
uint64_t len;
|
||||||
|
fread(&len, 8, 1, f);
|
||||||
|
v.as.String.cstr = malloc(len + 1);
|
||||||
|
if (v.as.String.cstr == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
fread(v.as.String.cstr, 1, len, f);
|
||||||
|
v.as.String.cstr[len] = '\0';
|
||||||
|
v.as.String.len = len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("unknown value type in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundBytecode _GroundBytecodeLoad(const char* path) {
|
||||||
|
GroundBytecode bc = {0};
|
||||||
|
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
Ground.Log.Error("failed to open file for reading in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
char magic[8];
|
||||||
|
memset(magic, 0, 8);
|
||||||
|
if (fread(magic, 7, 1, f) != 1 || memcmp(magic, "GRNDbc", 6) != 0) {
|
||||||
|
Ground.Log.Error("bad magic in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t version;
|
||||||
|
fread(&version, 4, 1, f);
|
||||||
|
|
||||||
|
uint64_t count;
|
||||||
|
fread(&count, 8, 1, f);
|
||||||
|
if (count > 0) {
|
||||||
|
bc.heap.heap = malloc(sizeof(GroundValue) * count);
|
||||||
|
if (bc.heap.heap == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
for (uint64_t i = 0; i < count; i++) {
|
||||||
|
bc.heap.heap[i] = readValue(f);
|
||||||
|
if (Ground.Flags.error) {
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bc.heap.capacity = count;
|
||||||
|
bc.heap.len = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(&count, 8, 1, f);
|
||||||
|
if (count > 0) {
|
||||||
|
bc.program.at = malloc(sizeof(GroundBytecodeInstruction) * count);
|
||||||
|
if (bc.program.at == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
bc.program.capacity = count;
|
||||||
|
bc.program.len = count;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < count; i++) {
|
||||||
|
uint8_t type;
|
||||||
|
fread(&type, 1, 1, f);
|
||||||
|
bc.program.at[i].type = (enum GroundInstructionType)type;
|
||||||
|
|
||||||
|
uint64_t argCount;
|
||||||
|
fread(&argCount, 8, 1, f);
|
||||||
|
if (argCount > 0) {
|
||||||
|
bc.program.at[i].args.at = malloc(sizeof(GroundSize) * argCount);
|
||||||
|
if (bc.program.at[i].args.at == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
fread(bc.program.at[i].args.at, sizeof(GroundSize), argCount, f);
|
||||||
|
} else {
|
||||||
|
bc.program.at[i].args.at = NULL;
|
||||||
|
}
|
||||||
|
bc.program.at[i].args.len = argCount;
|
||||||
|
bc.program.at[i].args.capacity = argCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
75
src/Bytecode/save.c
Normal file
75
src/Bytecode/save.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#include "../../include/ground.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void writeValue(FILE* f, GroundValue* v) {
|
||||||
|
switch (v->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
uint8_t tag = 0;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
fwrite(&v->as.Int, 8, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
uint8_t tag = 1;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
fwrite(&v->as.Double, 8, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Char: {
|
||||||
|
uint8_t tag = 2;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
fwrite(&v->as.Char, 1, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Bool: {
|
||||||
|
uint8_t tag = 3;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
fwrite(&v->as.Bool, 1, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_String: {
|
||||||
|
uint8_t tag = 4;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
uint64_t len = v->as.String.len;
|
||||||
|
fwrite(&len, 8, 1, f);
|
||||||
|
fwrite(v->as.String.cstr, 1, len, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
uint8_t tag = 0xFF;
|
||||||
|
fwrite(&tag, 1, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path) {
|
||||||
|
FILE* f = fopen(path, "wb");
|
||||||
|
if (f == NULL) {
|
||||||
|
Ground.Log.Error("failed to open file for writing in Ground.Bytecode.save");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite("GRNDbc\0", 7, 1, f);
|
||||||
|
uint32_t version = 1;
|
||||||
|
fwrite(&version, 4, 1, f);
|
||||||
|
|
||||||
|
uint64_t count = bytecode->heap.len;
|
||||||
|
fwrite(&count, 8, 1, f);
|
||||||
|
for (GroundSize i = 0; i < count; i++) {
|
||||||
|
writeValue(f, &bytecode->heap.heap[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
count = bytecode->program.len;
|
||||||
|
fwrite(&count, 8, 1, f);
|
||||||
|
for (GroundSize i = 0; i < count; i++) {
|
||||||
|
uint8_t type = (uint8_t)bytecode->program.at[i].type;
|
||||||
|
fwrite(&type, 1, 1, f);
|
||||||
|
uint64_t argCount = bytecode->program.at[i].args.len;
|
||||||
|
fwrite(&argCount, 8, 1, f);
|
||||||
|
fwrite(bytecode->program.at[i].args.at, 8, argCount, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
@@ -72,12 +72,6 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void addToGroundBytecodeProgram(GroundBytecodeProgram* program, GroundBytecodeInstruction inst) {
|
|
||||||
if (program->len + 1 >= program->capacity) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assigns an offset to each variable referenced.
|
* Assigns an offset to each variable referenced.
|
||||||
*/
|
*/
|
||||||
@@ -111,6 +105,7 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
item->_offset = size++;
|
item->_offset = size++;
|
||||||
snprintf(item->name, sizeof(item->name) - 1, "_._.ground_internal_constant_%zu", item->_offset);
|
snprintf(item->name, sizeof(item->name) - 1, "_._.ground_internal_constant_%zu", item->_offset);
|
||||||
HASH_ADD_STR(state->variables, name, item);
|
HASH_ADD_STR(state->variables, name, item);
|
||||||
|
arg->_offset = item->_offset;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +126,6 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
}
|
}
|
||||||
|
|
||||||
arg->_offset = item->_offset;
|
arg->_offset = item->_offset;
|
||||||
size++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to GroundBytecodeInstruction
|
// Convert to GroundBytecodeInstruction
|
||||||
@@ -142,7 +136,11 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
.args.capacity = gp->at[i].args.len
|
.args.capacity = gp->at[i].args.len
|
||||||
};
|
};
|
||||||
|
|
||||||
if (inst.args.at == NULL) {}
|
if (inst.args.at == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
|
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
|
||||||
inst.args.at[j] = gp->at[i].args.at[j]._offset;
|
inst.args.at[j] = gp->at[i].args.at[j]._offset;
|
||||||
@@ -196,12 +194,10 @@ GroundBytecode _GroundNewBytecode(GroundProgram* program, GroundState* state) {
|
|||||||
|
|
||||||
GroundVariable *s, *tmp;
|
GroundVariable *s, *tmp;
|
||||||
|
|
||||||
// Copy constants into heap
|
// Copy constants into heap at their assigned offsets
|
||||||
GroundSize i = 0;
|
|
||||||
HASH_ITER(hh, state->variables, s, tmp) {
|
HASH_ITER(hh, state->variables, s, tmp) {
|
||||||
bytecode.heap.heap[i] = Ground.Copy.Value(&s->value);
|
bytecode.heap.heap[s->_offset] = Ground.Copy.Value(&s->value);
|
||||||
if (Ground.Flags.error) return bytecode;
|
if (Ground.Flags.error) return bytecode;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
107
src/cli/main.c
Normal file
107
src/cli/main.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "../../include/ground.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
enum ArgsAction {
|
||||||
|
ARGS_HELP, ARGS_EXECUTE, ARGS_DEBUG, ARGS_ASSEMBLE, ARGS_DISASSEMBLE
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Args {
|
||||||
|
enum ArgsAction action;
|
||||||
|
char* inputFile;
|
||||||
|
char* outputFile;
|
||||||
|
} Args;
|
||||||
|
|
||||||
|
Args parseArgs(int argc, char** argv) {
|
||||||
|
Args args = {
|
||||||
|
.action = ARGS_EXECUTE,
|
||||||
|
.inputFile = NULL,
|
||||||
|
.outputFile = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (argc == 1) {
|
||||||
|
args.action = ARGS_HELP;
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
char* arg = argv[i];
|
||||||
|
|
||||||
|
if (strcmp(arg, "-d") == 0 || strcmp(arg, "--debug") == 0) {
|
||||||
|
args.action = ARGS_DEBUG;
|
||||||
|
} else if (strcmp(arg, "-a") == 0 || strcmp(arg, "--assemble") == 0) {
|
||||||
|
args.action = ARGS_ASSEMBLE;
|
||||||
|
if (i + i < argc) {
|
||||||
|
i++;
|
||||||
|
args.outputFile = argv[i];
|
||||||
|
}
|
||||||
|
} else if (strcmp(arg, "-D") == 0 || strcmp(arg, "--disassemble") == 0) {
|
||||||
|
args.action = ARGS_DISASSEMBLE;
|
||||||
|
} else if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||||
|
args.action = ARGS_HELP;
|
||||||
|
} else {
|
||||||
|
args.inputFile = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
Args args = parseArgs(argc, argv);
|
||||||
|
|
||||||
|
if (args.inputFile == NULL) {
|
||||||
|
fprintf(stderr, "Please specify a bytecode file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (args.action) {
|
||||||
|
case ARGS_EXECUTE: {
|
||||||
|
GroundBytecode bc = Ground.Bytecode.load(args.inputFile);
|
||||||
|
if (Ground.Flags.error) {
|
||||||
|
fprintf(stderr, "Failed to load bytecode, printing errors...\n");
|
||||||
|
Ground.Log.printErrors();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ground.Bytecode.Program.execute(&bc.program, &bc.heap);
|
||||||
|
if (Ground.Flags.error) {
|
||||||
|
fprintf(stderr, "Failed to run program, printing errors...\n");
|
||||||
|
Ground.Log.printErrors();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARGS_DEBUG: {
|
||||||
|
fprintf(stderr, "Not yet implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARGS_ASSEMBLE: {
|
||||||
|
fprintf(stderr, "Not yet implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARGS_DISASSEMBLE: {
|
||||||
|
fprintf(stderr, "Not yet implemented");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARGS_HELP: {
|
||||||
|
printf("GroundVM cli help\n");
|
||||||
|
printf("Usage: %s <file.gb> [-h] [--help] [-d] [--debug] [-a <file.grnd>] [--assemble <file.grnd>] [-D] [--disassemble]\n", argv[0]);
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -h or --help\n");
|
||||||
|
printf(" Shows this help message\n");
|
||||||
|
printf(" -d or --debug\n");
|
||||||
|
printf(" Interactive debugger for a Ground program\n");
|
||||||
|
printf(" -a <file.grnd> or --assemble <file.grnd>\n");
|
||||||
|
printf(" Assembles a .grnd textual representation into a .gb bytecode file\n");
|
||||||
|
printf(" Inputs from <file.grnd>, outputs to <file.gb>\n");
|
||||||
|
printf(" -D or --disassemble\n");
|
||||||
|
printf(" Disassembles a .gb program, showing the heap, instructions, and offsets\n");
|
||||||
|
printf("If no options are specified, the provided <file.gb> will be executed.\n");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -100,6 +100,9 @@ void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program);
|
|||||||
|
|
||||||
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
|
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
|
||||||
|
|
||||||
|
void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path);
|
||||||
|
GroundBytecode _GroundBytecodeLoad(const char* path);
|
||||||
|
|
||||||
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);
|
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);
|
||||||
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx);
|
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx);
|
||||||
|
|
||||||
@@ -223,6 +226,8 @@ struct _Ground Ground = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.Bytecode = {
|
.Bytecode = {
|
||||||
|
.save = _GroundBytecodeSave,
|
||||||
|
.load = _GroundBytecodeLoad,
|
||||||
.Program = {
|
.Program = {
|
||||||
.execute = _GroundBytecodeProgramExecute,
|
.execute = _GroundBytecodeProgramExecute,
|
||||||
.optimise = _GroundBytecodeProgramOptimise,
|
.optimise = _GroundBytecodeProgramOptimise,
|
||||||
|
|||||||
29
test/test.c
29
test/test.c
@@ -1,29 +0,0 @@
|
|||||||
#include <ground.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
GroundProgram program = Ground.New.Program();
|
|
||||||
GroundState state = {NULL, NULL, NULL};
|
|
||||||
|
|
||||||
// Instruction 1: CREATELABEL start
|
|
||||||
GroundInstruction label_inst = Ground.New.Instruction(GroundInstruction_CREATELABEL);
|
|
||||||
Ground.Instruction.append(&label_inst, Ground.New.Arg.LabelRef("start"));
|
|
||||||
Ground.Program.append(&program, label_inst);
|
|
||||||
|
|
||||||
// Instruction 2: JUMP start
|
|
||||||
GroundInstruction jump_inst = Ground.New.Instruction(GroundInstruction_JUMP);
|
|
||||||
Ground.Instruction.append(&jump_inst, Ground.New.Arg.LabelRef("start"));
|
|
||||||
Ground.Program.append(&program, jump_inst);
|
|
||||||
|
|
||||||
// Execute program
|
|
||||||
Ground.Program.execute(&program, &state);
|
|
||||||
|
|
||||||
if (Ground.Flags.error) {
|
|
||||||
printf("Error set during execution!\n");
|
|
||||||
Ground.Log.printErrors();
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("Success!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user