diff --git a/include/ground.h b/include/ground.h index 6fd9e24..9570494 100644 --- a/include/ground.h +++ b/include/ground.h @@ -336,7 +336,7 @@ struct _Ground { struct { void (*append) (GroundInstruction* instruction, GroundArg arg); - void (*execute) (GroundInstruction* instruction, GroundState* state); + int64_t (*execute) (GroundInstruction* instruction, GroundValue* heap); } Instruction; struct { diff --git a/src/Instruction/execute.c b/src/Instruction/execute.c index 0ae68ac..bbc716e 100644 --- a/src/Instruction/execute.c +++ b/src/Instruction/execute.c @@ -1,6 +1,7 @@ #include "../../include/ground.h" #include #include +#include /* * Return values guide: @@ -123,9 +124,19 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h printf("\n"); return -1; } - SET: {} - GETTYPE: {} - EXISTS: {} + SET: { + size_t 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: {} SETLISTAT: {} GETLISTAT: {} @@ -133,13 +144,374 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h LISTAPPEND: {} GETSTRSIZE: {} GETSTRCHARAT: {} - ADD: {} - SUBTRACT: {} - MULTIPLY: {} - DIVIDE: {} - EQUAL: {} - INEQUAL: {} - NOT: {} + 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: {} LESSER: {} AND: {} @@ -172,4 +544,8 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h THROW: {} CATCH: {} + Ground.Log.Error("operation fell through in Ground.Instruction.execute()"); + Ground.Flags.error = true; + + return -1; } diff --git a/src/Internal/run.c b/src/Internal/run.c index cf601e2..743602b 100644 --- a/src/Internal/run.c +++ b/src/Internal/run.c @@ -40,6 +40,8 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { return; } + arg->_offset = *line; + } else if (instruction->type == GroundInstruction_IF) { GroundArg* arg = &instruction->args.at[1]; size_t* line = Ground.State.findLabel(state, arg->as.ref); @@ -50,6 +52,8 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { Ground.Flags.error = true; return; } + + arg->_offset = *line; } else if (instruction->type == GroundInstruction_CATCH) { GroundArg* arg = &instruction->args.at[1]; @@ -62,6 +66,8 @@ static inline void doLabels(GroundProgram* program, GroundState* state) { return; } + arg->_offset = *line; + } }