progress
This commit is contained in:
@@ -23,6 +23,7 @@ typedef struct GroundState GroundState;
|
|||||||
typedef struct GroundBytecodeProgram GroundBytecodeProgram;
|
typedef struct GroundBytecodeProgram GroundBytecodeProgram;
|
||||||
typedef struct GroundBytecodeInstruction GroundBytecodeInstruction;
|
typedef struct GroundBytecodeInstruction GroundBytecodeInstruction;
|
||||||
typedef struct GroundBytecodeHeap GroundBytecodeHeap;
|
typedef struct GroundBytecodeHeap GroundBytecodeHeap;
|
||||||
|
typedef struct GroundBytecode GroundBytecode;
|
||||||
|
|
||||||
// --- Literal types ---
|
// --- Literal types ---
|
||||||
|
|
||||||
@@ -267,7 +268,7 @@ struct GroundBytecodeProgram {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct GroundBytecodeInstruction {
|
struct GroundBytecodeInstruction {
|
||||||
GroundInstruction instruction;
|
enum GroundInstructionType type;
|
||||||
struct {
|
struct {
|
||||||
GroundSize* at;
|
GroundSize* at;
|
||||||
GroundSize capacity;
|
GroundSize capacity;
|
||||||
@@ -278,9 +279,13 @@ struct GroundBytecodeInstruction {
|
|||||||
struct GroundBytecodeHeap {
|
struct GroundBytecodeHeap {
|
||||||
GroundValue* heap;
|
GroundValue* heap;
|
||||||
GroundSize capacity;
|
GroundSize capacity;
|
||||||
GroundSize count;
|
GroundSize len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GroundBytecode {
|
||||||
|
GroundBytecodeProgram program;
|
||||||
|
GroundBytecodeHeap heap;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// INTERFACE
|
// INTERFACE
|
||||||
@@ -335,6 +340,8 @@ struct _Ground {
|
|||||||
|
|
||||||
GroundIdentifier* (*Identifier) (const char* id);
|
GroundIdentifier* (*Identifier) (const char* id);
|
||||||
|
|
||||||
|
GroundBytecode (*Bytecode) (GroundProgram* program, GroundState* state);
|
||||||
|
|
||||||
} New;
|
} New;
|
||||||
|
|
||||||
// Frees the memory held by the specified struct
|
// Frees the memory held by the specified struct
|
||||||
@@ -422,8 +429,13 @@ struct _Ground {
|
|||||||
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
|
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
|
||||||
void (*optimise) (GroundBytecodeProgram* program);
|
void (*optimise) (GroundBytecodeProgram* program);
|
||||||
} Program;
|
} Program;
|
||||||
struct {} Instruction;
|
struct {
|
||||||
struct {} Heap;
|
int64_t (*execute) (GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
|
||||||
|
} Instruction;
|
||||||
|
struct {
|
||||||
|
void (*set) (GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);
|
||||||
|
GroundValue* (*get) (GroundBytecodeHeap* heap, GroundSize idx);
|
||||||
|
} Heap;
|
||||||
} Bytecode;
|
} Bytecode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ project('ground', 'c', version : '0.1.0')
|
|||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
|
|
||||||
sources = files(
|
sources = files(
|
||||||
|
|
||||||
|
'src/Bytecode/Heap/get.c',
|
||||||
|
'src/Bytecode/Heap/set.c',
|
||||||
|
'src/Bytecode/Instruction/execute.c',
|
||||||
|
'src/Bytecode/Program/execute.c',
|
||||||
|
'src/Bytecode/Program/optimise.c',
|
||||||
|
|
||||||
'src/Copy/Arg.c',
|
'src/Copy/Arg.c',
|
||||||
'src/Copy/Function.c',
|
'src/Copy/Function.c',
|
||||||
'src/Copy/Instruction.c',
|
'src/Copy/Instruction.c',
|
||||||
@@ -64,6 +71,8 @@ sources = files(
|
|||||||
|
|
||||||
'src/New/Identifier.c',
|
'src/New/Identifier.c',
|
||||||
|
|
||||||
|
'src/New/Bytecode.c',
|
||||||
|
|
||||||
'src/New/NativeFunction.c',
|
'src/New/NativeFunction.c',
|
||||||
|
|
||||||
'src/New/Instruction.c',
|
'src/New/Instruction.c',
|
||||||
|
|||||||
5
src/Bytecode/Heap/get.c
Normal file
5
src/Bytecode/Heap/get.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "../../../include/ground.h"
|
||||||
|
|
||||||
|
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx) {
|
||||||
|
return &heap->heap[idx];
|
||||||
|
}
|
||||||
5
src/Bytecode/Heap/set.c
Normal file
5
src/Bytecode/Heap/set.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "../../../include/ground.h"
|
||||||
|
|
||||||
|
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value) {
|
||||||
|
heap->heap[idx] = value;
|
||||||
|
}
|
||||||
600
src/Bytecode/Instruction/execute.c
Normal file
600
src/Bytecode/Instruction/execute.c
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
#include "../../../include/ground.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
|
||||||
|
|
||||||
|
static const void* jumpTable[] = {
|
||||||
|
&&IF, &&JUMP, &&END,
|
||||||
|
&&INPUT, &&PRINT, &&PRINTLN,
|
||||||
|
&&SET, &&GETTYPE, &&EXISTS,
|
||||||
|
&&SETLIST, &&SETLISTAT, &&GETLISTAT, &&GETLISTSIZE, &&LISTAPPEND,
|
||||||
|
&&GETSTRSIZE, &&GETSTRCHARAT,
|
||||||
|
&&ADD, &&SUBTRACT, &&MULTIPLY, &&DIVIDE,
|
||||||
|
&&EQUAL, &&INEQUAL, &&NOT, &&GREATER, &&LESSER,
|
||||||
|
&&AND, &&OR, &&XOR, &&NEG, &&SHIFT,
|
||||||
|
&&STOI, &&STOD, &&ITOC, &&CTOI, &&TOSTRING,
|
||||||
|
&&FUN, &&RETURN, &&ENDFUN, &&CALL, &&CALLMETHOD,
|
||||||
|
&&STRUCT, &&ENDSTRUCT, &&INIT, &&GETFIELD, &&SETFIELD,
|
||||||
|
&&USE, &&EXTERN, &&CREATELABEL,
|
||||||
|
&&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
|
||||||
|
};
|
||||||
|
|
||||||
|
// Jump to the spot
|
||||||
|
goto *jumpTable[instruction->type];
|
||||||
|
|
||||||
|
IF: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
JUMP: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
END: {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
INPUT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PRINT: {
|
||||||
|
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
||||||
|
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]);
|
||||||
|
switch (val->type.type) {
|
||||||
|
case GroundType_Int:
|
||||||
|
printf("%" PRId64, val->as.Int);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Double:
|
||||||
|
printf("%f", val->as.Double);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Bool:
|
||||||
|
printf(val->as.Bool ? "true" : "false");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Char:
|
||||||
|
printf("%c", val->as.Char);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_String:
|
||||||
|
printf("%s", val->as.String.cstr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("<fixme>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PRINTLN: {
|
||||||
|
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
||||||
|
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]);
|
||||||
|
switch (val->type.type) {
|
||||||
|
case GroundType_Int:
|
||||||
|
printf("%" PRId64, val->as.Int);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Double:
|
||||||
|
printf("%f", val->as.Double);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Bool:
|
||||||
|
printf(val->as.Bool ? "true" : "false");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_Char:
|
||||||
|
printf("%c", val->as.Char);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GroundType_String:
|
||||||
|
printf("%s", val->as.String.cstr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("<fixme>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SET: {
|
||||||
|
Ground.Bytecode.Heap.set(heap, instruction->args.at[0], *Ground.Bytecode.Heap.get(heap, instruction->args.at[1]));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETTYPE: {
|
||||||
|
Ground.Log.Warning("GETTYPE is deprecated");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXISTS: {
|
||||||
|
Ground.Log.Warning("EXISTS is deprecated");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SETLIST: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SETLISTAT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETLISTAT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETLISTSIZE: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LISTAPPEND: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETSTRSIZE: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETSTRCHARAT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ADD: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Int(left->as.Int + right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Int + right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double + right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double + right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_String: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_String: {
|
||||||
|
char* buf = malloc(sizeof(char) * (left->as.String.len + right->as.String.len + 1));
|
||||||
|
if (buf == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sprintf(buf, "%s%s", left->as.String.cstr, right->as.String.cstr);
|
||||||
|
*final = Ground.New.Value.String(Ground.New.String(buf));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SUBTRACT: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Int(left->as.Int - right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Int - right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double - right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double - right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
MULTIPLY: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Int(left->as.Int * right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Int * right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double * right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double * right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DIVIDE: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Int(left->as.Int / right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Int / right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double / right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Double(left->as.Double / right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EQUAL: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Int == right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Int == right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Double == right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Double == right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Char: {
|
||||||
|
if (right->type.type == GroundType_Char) {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Char == right->as.Char);
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Bool: {
|
||||||
|
if (right->type.type == GroundType_Bool) {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Bool == right->as.Bool);
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_String: {
|
||||||
|
if (right->type.type == GroundType_String) {
|
||||||
|
*final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr));
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// FIXME implement for complex types
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
INEQUAL: {
|
||||||
|
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
|
||||||
|
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
|
||||||
|
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
|
||||||
|
|
||||||
|
switch (left->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Int != right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Int != right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
*final = Ground.New.Value.Bool(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
switch (right->type.type) {
|
||||||
|
case GroundType_Int: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Double != right->as.Int);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Double: {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Double != right->as.Double);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
*final = Ground.New.Value.Bool(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Char: {
|
||||||
|
if (right->type.type == GroundType_Char) {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Char != right->as.Char);
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_Bool: {
|
||||||
|
if (right->type.type == GroundType_Bool) {
|
||||||
|
*final = Ground.New.Value.Bool(left->as.Bool != right->as.Bool);
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GroundType_String: {
|
||||||
|
if (right->type.type == GroundType_String) {
|
||||||
|
*final = Ground.New.Value.Bool(!strcmp(left->as.String.cstr, right->as.String.cstr));
|
||||||
|
} else {
|
||||||
|
*final = Ground.New.Value.Bool(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// FIXME implement for complex types
|
||||||
|
*final = Ground.New.Value.Bool(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
NOT: {
|
||||||
|
Ground.Bytecode.Heap.set(heap, instruction->args.at[1], Ground.New.Value.Bool(!Ground.Bytecode.Heap.get(heap, instruction->args.at[0])->as.Bool));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GREATER: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LESSER: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
AND: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
OR: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
XOR: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
NEG: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SHIFT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
STOI: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
STOD: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ITOC: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CTOI: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
TOSTRING: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FUN: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
RETURN: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ENDFUN: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CALL: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CALLMETHOD: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
STRUCT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ENDSTRUCT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
INIT: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
GETFIELD: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SETFIELD: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
USE: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXTERN: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CREATELABEL: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PAUSE: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DROP: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LICENSE: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ERRORCMD: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
THROW: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CATCH: {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
17
src/Bytecode/Program/execute.c
Normal file
17
src/Bytecode/Program/execute.c
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "../../../include/ground.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) {
|
||||||
|
for (GroundSize i = 0; i < program->len; i++) {
|
||||||
|
int64_t status = Ground.Bytecode.Instruction.execute(&program->at[i], heap);
|
||||||
|
if (Ground.Flags.error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case -1: break;
|
||||||
|
case -2: return;
|
||||||
|
default: i = status; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/Bytecode/Program/optimise.c
Normal file
5
src/Bytecode/Program/optimise.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "../../../include/ground.h"
|
||||||
|
|
||||||
|
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program) {
|
||||||
|
// TODO: Implement optimisation
|
||||||
|
}
|
||||||
@@ -11,617 +11,5 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* heap) {
|
int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* heap) {
|
||||||
|
|
||||||
static const void* jumpTable[] = {
|
|
||||||
&&IF, &&JUMP, &&END,
|
|
||||||
&&INPUT, &&PRINT, &&PRINTLN,
|
|
||||||
&&SET, &&GETTYPE, &&EXISTS,
|
|
||||||
&&SETLIST, &&SETLISTAT, &&GETLISTAT, &&GETLISTSIZE, &&LISTAPPEND,
|
|
||||||
&&GETSTRSIZE, &&GETSTRCHARAT,
|
|
||||||
&&ADD, &&SUBTRACT, &&MULTIPLY, &&DIVIDE,
|
|
||||||
&&EQUAL, &&INEQUAL, &&NOT, &&GREATER, &&LESSER,
|
|
||||||
&&AND, &&OR, &&XOR, &&NEG, &&SHIFT,
|
|
||||||
&&STOI, &&STOD, &&ITOC, &&CTOI, &&TOSTRING,
|
|
||||||
&&FUN, &&RETURN, &&ENDFUN, &&CALL, &&CALLMETHOD,
|
|
||||||
&&STRUCT, &&ENDSTRUCT, &&INIT, &&GETFIELD, &&SETFIELD,
|
|
||||||
&&USE, &&EXTERN, &&CREATELABEL,
|
|
||||||
&&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
|
|
||||||
};
|
|
||||||
|
|
||||||
// Preprocess any ValueRefs
|
|
||||||
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
|
||||||
if (instruction->args.at[i].type == GroundArg_ValueRef) {
|
|
||||||
GroundSize offset = instruction->args.at[i]._offset;
|
|
||||||
instruction->args.at[i] = Ground.New.Arg.Value(heap[offset]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Jump to the spot
|
|
||||||
goto *jumpTable[instruction->type];
|
|
||||||
|
|
||||||
IF: {
|
|
||||||
if (instruction->args.at[0].as.value.as.Bool) {
|
|
||||||
return instruction->args.at[1]._offset;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JUMP: {
|
|
||||||
return instruction->args.at[0]._offset;
|
|
||||||
}
|
|
||||||
END: {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
INPUT: {
|
|
||||||
char input[2048];
|
|
||||||
fgets(input, sizeof(input) - 1, stdin);
|
|
||||||
input[2047] = '\0';
|
|
||||||
|
|
||||||
GroundString string = Ground.New.String(input);
|
|
||||||
GroundValue value = Ground.New.Value.String(string);
|
|
||||||
heap[instruction->args.at[0]._offset] = value;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PRINT: {
|
|
||||||
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
|
||||||
GroundValue* val = &instruction->args.at[i].as.value;
|
|
||||||
switch (val->type.type) {
|
|
||||||
case GroundType_Int:
|
|
||||||
printf("%" PRId64, val->as.Int);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Double:
|
|
||||||
printf("%f", val->as.Double);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Bool:
|
|
||||||
printf(val->as.Bool ? "true" : "false");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Char:
|
|
||||||
printf("%c", val->as.Char);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_String:
|
|
||||||
printf("%s", val->as.String.cstr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("<fixme>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PRINTLN: {
|
|
||||||
for (GroundSize i = 0; i < instruction->args.len; i++) {
|
|
||||||
GroundValue* val = &instruction->args.at[i].as.value;
|
|
||||||
switch (val->type.type) {
|
|
||||||
case GroundType_Int:
|
|
||||||
printf("%" PRId64, val->as.Int);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Double:
|
|
||||||
printf("%f", val->as.Double);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Bool:
|
|
||||||
printf(val->as.Bool ? "true" : "false");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_Char:
|
|
||||||
printf("%c", val->as.Char);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GroundType_String:
|
|
||||||
printf("%s", val->as.String.cstr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("<fixme>");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SET: {
|
|
||||||
GroundSize offset = instruction->args.at[0]._offset;
|
|
||||||
heap[offset] = instruction->args.at[1].as.value;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETTYPE: {
|
|
||||||
Ground.Log.Warning("GETTYPE is deprecated");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
EXISTS: {
|
|
||||||
Ground.Log.Warning("EXISTS is deprecated");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SETLIST: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SETLISTAT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETLISTAT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETLISTSIZE: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
LISTAPPEND: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETSTRSIZE: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETSTRCHARAT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ADD: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Int(left->as.Int + right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Int + right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double + right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double + right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_String: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_String: {
|
|
||||||
char* buf = malloc(sizeof(char) * (left->as.String.len + right->as.String.len + 1));
|
|
||||||
if (buf == NULL) {
|
|
||||||
Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sprintf(buf, "%s%s", left->as.String.cstr, right->as.String.cstr);
|
|
||||||
*final = Ground.New.Value.String(Ground.New.String(buf));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SUBTRACT: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Int(left->as.Int - right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Int - right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double - right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double - right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
MULTIPLY: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Int(left->as.Int * right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Int * right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double * right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double * right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
DIVIDE: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Int(left->as.Int / right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Int / right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double / right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Double(left->as.Double / right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
EQUAL: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Int == right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Int == right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Double == right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Double == right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Char: {
|
|
||||||
if (right->type.type == GroundType_Char) {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Char == right->as.Char);
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Bool: {
|
|
||||||
if (right->type.type == GroundType_Bool) {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Bool == right->as.Bool);
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_String: {
|
|
||||||
if (right->type.type == GroundType_String) {
|
|
||||||
*final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr));
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// FIXME implement for complex types
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
INEQUAL: {
|
|
||||||
GroundValue* final = &heap[instruction->args.at[2]._offset];
|
|
||||||
GroundValue* left = &instruction->args.at[0].as.value;
|
|
||||||
GroundValue* right = &instruction->args.at[1].as.value;
|
|
||||||
|
|
||||||
switch (left->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Int != right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Int != right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
*final = Ground.New.Value.Bool(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
switch (right->type.type) {
|
|
||||||
case GroundType_Int: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Double != right->as.Int);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Double: {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Double != right->as.Double);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
*final = Ground.New.Value.Bool(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Char: {
|
|
||||||
if (right->type.type == GroundType_Char) {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Char != right->as.Char);
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_Bool: {
|
|
||||||
if (right->type.type == GroundType_Bool) {
|
|
||||||
*final = Ground.New.Value.Bool(left->as.Bool != right->as.Bool);
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GroundType_String: {
|
|
||||||
if (right->type.type == GroundType_String) {
|
|
||||||
*final = Ground.New.Value.Bool(!strcmp(left->as.String.cstr, right->as.String.cstr));
|
|
||||||
} else {
|
|
||||||
*final = Ground.New.Value.Bool(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// FIXME implement for complex types
|
|
||||||
*final = Ground.New.Value.Bool(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NOT: {
|
|
||||||
heap[instruction->args.at[1]._offset] = Ground.New.Value.Bool(!instruction->args.at[0].as.value.as.Bool);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GREATER: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
LESSER: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
AND: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
OR: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
XOR: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
NEG: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SHIFT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
STOI: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
STOD: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ITOC: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
CTOI: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
TOSTRING: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
FUN: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
RETURN: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ENDFUN: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
CALL: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
CALLMETHOD: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
STRUCT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ENDSTRUCT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
INIT: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
GETFIELD: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SETFIELD: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
USE: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
EXTERN: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
CREATELABEL: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PAUSE: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
DROP: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
LICENSE: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ERRORCMD: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
THROW: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
CATCH: {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,148 +1,15 @@
|
|||||||
#include "../../include/ground.h"
|
#include "../../include/ground.h"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <uthash.h>
|
|
||||||
|
|
||||||
static inline void doLabels(GroundProgram* program, GroundState* state) {
|
|
||||||
|
|
||||||
for (GroundSize i = 0; i < program->len; i++) {
|
|
||||||
GroundInstruction* instruction = &program->at[i];
|
|
||||||
if (instruction->type == GroundInstruction_CREATELABEL) {
|
|
||||||
if (instruction->args.len > 0) {
|
|
||||||
GroundArg* arg = &instruction->args.at[0];
|
|
||||||
GroundLabel* label = NULL;
|
|
||||||
HASH_FIND_STR(state->labels, arg->as.ref->string, label);
|
|
||||||
|
|
||||||
if (label == NULL) {
|
|
||||||
label = malloc(sizeof(GroundLabel));
|
|
||||||
if (label == NULL) {
|
|
||||||
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strncpy(label->name, arg->as.ref->string, 2047);
|
|
||||||
label->name[2047] = '\0';
|
|
||||||
label->lineNum = i;
|
|
||||||
HASH_ADD_STR(state->labels, name, label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (GroundSize i = 0; i < program->len; i++) {
|
|
||||||
GroundInstruction* instruction = &program->at[i];
|
|
||||||
if (instruction->type == GroundInstruction_JUMP) {
|
|
||||||
GroundArg* arg = &instruction->args.at[0];
|
|
||||||
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
|
||||||
if (line == NULL) {
|
|
||||||
char buf[2048];
|
|
||||||
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
|
||||||
Ground.Log.Error(buf);
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg->_offset = *line;
|
|
||||||
|
|
||||||
} else if (instruction->type == GroundInstruction_IF) {
|
|
||||||
GroundArg* arg = &instruction->args.at[1];
|
|
||||||
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
|
||||||
if (line == NULL) {
|
|
||||||
char buf[2048];
|
|
||||||
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
|
||||||
Ground.Log.Error(buf);
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg->_offset = *line;
|
|
||||||
|
|
||||||
} else if (instruction->type == GroundInstruction_CATCH) {
|
|
||||||
GroundArg* arg = &instruction->args.at[1];
|
|
||||||
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
|
||||||
if (line == NULL) {
|
|
||||||
char buf[2048];
|
|
||||||
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
|
||||||
Ground.Log.Error(buf);
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg->_offset = *line;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assigns an offset to each variable referenced.
|
|
||||||
*/
|
|
||||||
static inline GroundSize doOffsets(GroundProgram* program, GroundState* state) {
|
|
||||||
GroundSize size = 0;
|
|
||||||
for (GroundSize i = 0; i < program->len; i++) {
|
|
||||||
for (GroundSize j = 0; j < program->at[i].args.len; j++) {
|
|
||||||
GroundArg* arg = &program->at[i].args.at[j];
|
|
||||||
|
|
||||||
if (
|
|
||||||
arg->type == GroundArg_Value ||
|
|
||||||
arg->type == GroundArg_Label ||
|
|
||||||
arg->type == GroundArg_LineRef
|
|
||||||
) continue;
|
|
||||||
|
|
||||||
GroundVariable* item = NULL;
|
|
||||||
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
|
|
||||||
|
|
||||||
if (item == NULL) {
|
|
||||||
item = malloc(sizeof(GroundVariable));
|
|
||||||
if (item == NULL) {
|
|
||||||
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
item->value = Ground.New.Value.Int(0);
|
|
||||||
strncpy(item->name, arg->as.ref->string, 2047);
|
|
||||||
item->_offset = size++;
|
|
||||||
HASH_ADD_STR(state->variables, name, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
arg->_offset = item->_offset;
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _GroundInternalRun(GroundProgram* program, GroundState* state) {
|
void _GroundInternalRun(GroundProgram* program, GroundState* state) {
|
||||||
|
GroundBytecode bytecode = Ground.New.Bytecode(program, state);
|
||||||
// Precompute some really cool stuff
|
if (Ground.Flags.error) {
|
||||||
doLabels(program, state);
|
|
||||||
if (Ground.Flags.error) return;
|
|
||||||
|
|
||||||
GroundSize size = doOffsets(program, state);
|
|
||||||
if (Ground.Flags.error) return;
|
|
||||||
|
|
||||||
GroundValue* heap = malloc(sizeof(GroundValue) * size);
|
|
||||||
|
|
||||||
for (GroundSize i = 0; i < program->len; i++) {
|
|
||||||
GroundInstruction instruction = Ground.Copy.Instruction(&program->at[i]);
|
|
||||||
int64_t status = Ground.Instruction.execute(&instruction, heap);
|
|
||||||
switch (status) {
|
|
||||||
case -2:
|
|
||||||
return;
|
|
||||||
case -1:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (status < program->len) {
|
|
||||||
i = status - 1;
|
|
||||||
} else {
|
|
||||||
Ground.Log.Error("out of bounds jump in Ground.Internal.Run()");
|
|
||||||
Ground.Flags.error = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ground.Free.Instruction(&instruction);
|
Ground.Bytecode.Program.optimise(&bytecode.program);
|
||||||
|
if (Ground.Flags.error) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ground.Bytecode.Program.execute(&bytecode.program, &bytecode.heap);
|
||||||
}
|
}
|
||||||
|
|||||||
210
src/New/Bytecode.c
Normal file
210
src/New/Bytecode.c
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
#include "../../include/ground.h"
|
||||||
|
|
||||||
|
static inline void doLabels(GroundProgram* program, GroundState* state) {
|
||||||
|
|
||||||
|
for (GroundSize i = 0; i < program->len; i++) {
|
||||||
|
GroundInstruction* instruction = &program->at[i];
|
||||||
|
if (instruction->type == GroundInstruction_CREATELABEL) {
|
||||||
|
if (instruction->args.len > 0) {
|
||||||
|
GroundArg* arg = &instruction->args.at[0];
|
||||||
|
GroundLabel* label = NULL;
|
||||||
|
HASH_FIND_STR(state->labels, arg->as.ref->string, label);
|
||||||
|
|
||||||
|
if (label == NULL) {
|
||||||
|
label = malloc(sizeof(GroundLabel));
|
||||||
|
if (label == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strncpy(label->name, arg->as.ref->string, 2047);
|
||||||
|
label->name[2047] = '\0';
|
||||||
|
label->lineNum = i;
|
||||||
|
HASH_ADD_STR(state->labels, name, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GroundSize i = 0; i < program->len; i++) {
|
||||||
|
GroundInstruction* instruction = &program->at[i];
|
||||||
|
if (instruction->type == GroundInstruction_JUMP) {
|
||||||
|
GroundArg* arg = &instruction->args.at[0];
|
||||||
|
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
||||||
|
if (line == NULL) {
|
||||||
|
char buf[2048];
|
||||||
|
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
||||||
|
Ground.Log.Error(buf);
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg->_offset = *line;
|
||||||
|
|
||||||
|
} else if (instruction->type == GroundInstruction_IF) {
|
||||||
|
GroundArg* arg = &instruction->args.at[1];
|
||||||
|
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
||||||
|
if (line == NULL) {
|
||||||
|
char buf[2048];
|
||||||
|
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
||||||
|
Ground.Log.Error(buf);
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg->_offset = *line;
|
||||||
|
|
||||||
|
} else if (instruction->type == GroundInstruction_CATCH) {
|
||||||
|
GroundArg* arg = &instruction->args.at[1];
|
||||||
|
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
|
||||||
|
if (line == NULL) {
|
||||||
|
char buf[2048];
|
||||||
|
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
|
||||||
|
Ground.Log.Error(buf);
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg->_offset = *line;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void addToGroundBytecodeProgram(GroundBytecodeProgram* program, GroundBytecodeInstruction inst) {
|
||||||
|
if (program->len + 1 >= program->capacity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assigns an offset to each variable referenced.
|
||||||
|
*/
|
||||||
|
static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, GroundBytecodeProgram* gbp) {
|
||||||
|
GroundSize size = 0;
|
||||||
|
|
||||||
|
// Add size of state
|
||||||
|
GroundVariable *s, *tmp;
|
||||||
|
HASH_ITER(hh, state->variables, s, tmp) {
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GroundSize i = 0; i < gp->len; i++) {
|
||||||
|
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
|
||||||
|
GroundArg* arg = &gp->at[i].args.at[j];
|
||||||
|
|
||||||
|
if (
|
||||||
|
arg->type == GroundArg_Label ||
|
||||||
|
arg->type == GroundArg_LineRef
|
||||||
|
) continue;
|
||||||
|
|
||||||
|
if (arg->type == GroundArg_Value) {
|
||||||
|
GroundVariable* item = malloc(sizeof(GroundVariable));
|
||||||
|
if (item == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
item->value = Ground.Copy.Value(&arg->as.value);
|
||||||
|
if (Ground.Flags.error) return 0;
|
||||||
|
item->_offset = size++;
|
||||||
|
snprintf(item->name, sizeof(item->name) - 1, "_._.ground_internal_constant_%zu", item->_offset);
|
||||||
|
HASH_ADD_STR(state->variables, name, item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundVariable* item = NULL;
|
||||||
|
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
|
||||||
|
|
||||||
|
if (item == NULL) {
|
||||||
|
item = malloc(sizeof(GroundVariable));
|
||||||
|
if (item == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Internal.run()");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
item->value = Ground.New.Value.Int(0);
|
||||||
|
strncpy(item->name, arg->as.ref->string, 2047);
|
||||||
|
item->_offset = size++;
|
||||||
|
HASH_ADD_STR(state->variables, name, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
arg->_offset = item->_offset;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to GroundBytecodeInstruction
|
||||||
|
GroundBytecodeInstruction inst = {
|
||||||
|
.type = gp->at[i].type,
|
||||||
|
.args.at = malloc(sizeof(GroundSize) * gp->at[i].args.len),
|
||||||
|
.args.len = gp->at[i].args.len,
|
||||||
|
.args.capacity = gp->at[i].args.len
|
||||||
|
};
|
||||||
|
|
||||||
|
if (inst.args.at == NULL) {}
|
||||||
|
|
||||||
|
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
|
||||||
|
inst.args.at[j] = gp->at[i].args.at[j]._offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbp->at[i] = inst;
|
||||||
|
gbp->len++;
|
||||||
|
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GroundBytecode _GroundNewBytecode(GroundProgram* program, GroundState* state) {
|
||||||
|
|
||||||
|
GroundBytecode bytecode = {
|
||||||
|
.program = {
|
||||||
|
.at = malloc(sizeof(GroundBytecodeInstruction) * program->len),
|
||||||
|
.capacity = program->len,
|
||||||
|
.len = 0,
|
||||||
|
},
|
||||||
|
.heap = {
|
||||||
|
.heap = NULL,
|
||||||
|
.capacity = 0,
|
||||||
|
.len = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bytecode.program.at == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.New.Bytecode");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return bytecode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precompute some really cool stuff
|
||||||
|
doLabels(program, state);
|
||||||
|
if (Ground.Flags.error) return bytecode;
|
||||||
|
|
||||||
|
GroundSize size = doOffsets(program, state, &bytecode.program);
|
||||||
|
if (Ground.Flags.error) return bytecode;
|
||||||
|
|
||||||
|
// Allocate heap
|
||||||
|
bytecode.heap.heap = malloc(sizeof(GroundValue) * size);
|
||||||
|
if (bytecode.heap.heap == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.New.Bytecode");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return bytecode;
|
||||||
|
}
|
||||||
|
bytecode.heap.capacity = size;
|
||||||
|
bytecode.heap.len = size;
|
||||||
|
|
||||||
|
GroundVariable *s, *tmp;
|
||||||
|
|
||||||
|
// Copy constants into heap
|
||||||
|
GroundSize i = 0;
|
||||||
|
HASH_ITER(hh, state->variables, s, tmp) {
|
||||||
|
bytecode.heap.heap[i] = Ground.Copy.Value(&s->value);
|
||||||
|
if (Ground.Flags.error) return bytecode;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return bytecode;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -32,6 +32,8 @@ GroundType _GroundNewType(enum GroundTypeType type, ...);
|
|||||||
|
|
||||||
GroundIdentifier* _GroundNewIdentifier(const char* id);
|
GroundIdentifier* _GroundNewIdentifier(const char* id);
|
||||||
|
|
||||||
|
GroundBytecode _GroundNewBytecode (GroundProgram* program, GroundState* state);
|
||||||
|
|
||||||
void _GroundFreeValue(GroundValue* in);
|
void _GroundFreeValue(GroundValue* in);
|
||||||
void _GroundFreeList(GroundList* in);
|
void _GroundFreeList(GroundList* in);
|
||||||
void _GroundFreeString(GroundString* in);
|
void _GroundFreeString(GroundString* in);
|
||||||
@@ -93,6 +95,13 @@ void _GroundLogWarning(const char* message);
|
|||||||
void _GroundLogPrintErrors();
|
void _GroundLogPrintErrors();
|
||||||
|
|
||||||
|
|
||||||
|
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
|
||||||
|
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program);
|
||||||
|
|
||||||
|
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
|
||||||
|
|
||||||
|
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);
|
||||||
|
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx);
|
||||||
|
|
||||||
|
|
||||||
struct _Ground Ground = {
|
struct _Ground Ground = {
|
||||||
@@ -136,6 +145,8 @@ struct _Ground Ground = {
|
|||||||
.Type = _GroundNewType,
|
.Type = _GroundNewType,
|
||||||
|
|
||||||
.Identifier = _GroundNewIdentifier,
|
.Identifier = _GroundNewIdentifier,
|
||||||
|
|
||||||
|
.Bytecode = _GroundNewBytecode,
|
||||||
},
|
},
|
||||||
|
|
||||||
.Free = {
|
.Free = {
|
||||||
@@ -210,4 +221,18 @@ struct _Ground Ground = {
|
|||||||
.errors = NULL,
|
.errors = NULL,
|
||||||
.warnings = NULL,
|
.warnings = NULL,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.Bytecode = {
|
||||||
|
.Program = {
|
||||||
|
.execute = _GroundBytecodeProgramExecute,
|
||||||
|
.optimise = _GroundBytecodeProgramOptimise,
|
||||||
|
},
|
||||||
|
.Instruction = {
|
||||||
|
.execute = _GroundBytecodeInstructionExecute,
|
||||||
|
},
|
||||||
|
.Heap = {
|
||||||
|
.set = _GroundBytecodeHeapSet,
|
||||||
|
.get = _GroundBytecodeHeapGet,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user