Compare commits

7 Commits

7 changed files with 129 additions and 23 deletions

View File

@@ -75,7 +75,7 @@ build
- [x] String operations - [x] String operations
- [x] Maths - [x] Maths
- [x] Comparisions - [x] Comparisions
- [ ] Type conversions - [x] Type conversions
- [x] Functions - [x] Functions
- [x] Define functions - [x] Define functions
- [x] Call functions - [x] Call functions
@@ -83,7 +83,7 @@ build
- [x] Arguments for functions - [x] Arguments for functions
- [x] Jumping within functions - [x] Jumping within functions
- [x] Custom data structures - [x] Custom data structures
- [ ] Working with external libraries - [x] Working with external libraries
## Debugger ## Debugger

View File

@@ -362,3 +362,23 @@ Looks in the path $GROUND_LIBS/`$libraryName`.grnd for the library. ($GROUND_LIB
Attempts to import a shared library written in a compiled language like C or C++ for usage within the current program. Attempts to import a shared library written in a compiled language like C or C++ for usage within the current program.
Looks in the path $GROUND_LIBS/`$libraryName`.so for the library. ($GROUND_LIBS is a system environment variable.) Looks in the path $GROUND_LIBS/`$libraryName`.so for the library. ($GROUND_LIBS is a system environment variable.)
### Data Structures
#### struct -structName
Creates a new struct which can be initialised. Until the endstruct keyword, the only valid instructions are init, set, fun, endfun, struct, and endstruct.
Any value created inside the struct will be added to the struct.
#### endstruct
Ends the creation of a struct.
#### getfield $object &fieldName &outputVar
Gets a field from an initialised object. fieldName must be a valid name of a field in the object. Errors if the field does not exist.
#### setfield &object &fieldName $value
Sets a field to a new value in the object. The value must be of the same type as the field's old value.

View File

@@ -443,6 +443,7 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs
addInstructionToProgram(&gp, in->instructions[i]); addInstructionToProgram(&gp, in->instructions[i]);
i++; i++;
} }
i--;
GroundFunction* function = parseFunction(&gp, errorOffset); GroundFunction* function = parseFunction(&gp, errorOffset);
function->startLine = i; function->startLine = i;
@@ -509,6 +510,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
addInstructionToProgram(&gp, in->instructions[i]); addInstructionToProgram(&gp, in->instructions[i]);
i++; i++;
} }
i--;
GroundFunction* function = parseFunction(&gp, errorOffset); GroundFunction* function = parseFunction(&gp, errorOffset);
function->startLine = i; function->startLine = i;
@@ -546,6 +548,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
addInstructionToProgram(&gp, in->instructions[i]); addInstructionToProgram(&gp, in->instructions[i]);
i++; i++;
} }
i--;
GroundValue gv = { GroundValue gv = {
.type = STRUCTVAL, .type = STRUCTVAL,
@@ -1104,7 +1107,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.args[1].type != DIRREF) { if (in->args.args[1].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
} }
addVariable(scope->variables, in->args.args[2].value.refName, createIntGroundValue(atoll(in->args.args[0].value.value.data.stringVal))); addVariable(scope->variables, in->args.args[1].value.refName, createIntGroundValue(atoll(in->args.args[0].value.value.data.stringVal)));
break; break;
} }
case STOD: { case STOD: {
@@ -1120,7 +1123,39 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.args[1].type != DIRREF) { if (in->args.args[1].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
} }
addVariable(scope->variables, in->args.args[1].value.refName, createIntGroundValue(atof(in->args.args[0].value.value.data.stringVal))); addVariable(scope->variables, in->args.args[1].value.refName, createDoubleGroundValue(atof(in->args.args[0].value.value.data.stringVal)));
break;
}
case ITOC: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.length > 2) {
runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.args[0].type != VALUE || in->args.args[0].value.value.type != INT) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
}
addVariable(scope->variables, in->args.args[1].value.refName, createCharGroundValue((char)in->args.args[0].value.value.data.intVal));
break;
}
case CTOI: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.length > 2) {
runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.args[0].type != VALUE || in->args.args[0].value.value.type != CHAR) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Char for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
}
addVariable(scope->variables, in->args.args[1].value.refName, createIntGroundValue((int)in->args.args[0].value.value.data.charVal));
break; break;
} }
case TOSTRING: { case TOSTRING: {
@@ -1137,57 +1172,53 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction);
} }
GroundValue* value = &in->args.args[0].value.value; GroundValue* value = &in->args.args[0].value.value;
char buf[256];
switch (value->type) { switch (value->type) {
case INT: { case INT: {
char* buf = malloc(sizeof(char) * 256); snprintf(buf, sizeof(buf) * 256, "%" PRId64, value->data.intVal);
snprintf(buf, sizeof(char) * 256, "%" PRId64, value->data.intVal);
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue(buf));
break; break;
} }
case DOUBLE: { case DOUBLE: {
char* buf = malloc(sizeof(char) * 256); snprintf(buf, sizeof(buf) * 256, "%f", value->data.doubleVal);
snprintf(buf, sizeof(char) * 256, "%f", value->data.doubleVal);
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue(buf));
break; break;
} }
case STRING: { case STRING: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue(value->data.stringVal)); snprintf(buf, sizeof(buf), "%s", value->data.stringVal);
break; break;
} }
case CHAR: { case CHAR: {
char* buf = malloc(sizeof(char) * 2);
buf[0] = value->data.charVal; buf[0] = value->data.charVal;
buf[1] = '\0'; buf[1] = '\0';
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue(buf));
break; break;
} }
case BOOL: { case BOOL: {
if (value->data.boolVal) { if (value->data.boolVal) {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("true")); snprintf(buf, sizeof(buf), "true");
} else { } else {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("false")); snprintf(buf, sizeof(buf), "false");
} }
break; break;
} }
case LIST: { case LIST: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("<list>")); snprintf(buf, sizeof(buf), "<list>");
break; break;
} }
case FUNCTION: { case FUNCTION: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("<function>")); snprintf(buf, sizeof(buf), "<function>");
break; break;
} }
case CUSTOM: { case CUSTOM: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("<custom>")); snprintf(buf, sizeof(buf), "<custom>");
break; break;
} }
case NONE: case NONE:
default: { default: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("<default>")); snprintf(buf, sizeof(buf), "<default>");
break; break;
} }
} }
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue(buf));
break; break;
} }

View File

@@ -159,6 +159,8 @@ static GroundInstType getInstructionType(const char* inst) {
if (strcmp(inst, "lesser") == 0) return LESSER; if (strcmp(inst, "lesser") == 0) return LESSER;
if (strcmp(inst, "stoi") == 0) return STOI; if (strcmp(inst, "stoi") == 0) return STOI;
if (strcmp(inst, "stod") == 0) return STOD; if (strcmp(inst, "stod") == 0) return STOD;
if (strcmp(inst, "ctoi") == 0) return CTOI;
if (strcmp(inst, "itoc") == 0) return ITOC;
if (strcmp(inst, "tostring") == 0) return TOSTRING; if (strcmp(inst, "tostring") == 0) return TOSTRING;
if (strcmp(inst, "fun") == 0) return FUN; if (strcmp(inst, "fun") == 0) return FUN;
if (strcmp(inst, "return") == 0) return RETURN; if (strcmp(inst, "return") == 0) return RETURN;

View File

@@ -149,8 +149,47 @@ void printGroundValue(GroundValue* gv) {
printf("<function>"); printf("<function>");
break; break;
} }
default: { case STRUCTVAL: {
printf("FIXME"); printf("<struct fields: { ");
for (size_t i = 0; i < gv->data.structVal->size; i++) {
if (i != 0) {
printf(", ");
}
printf("%s: ", gv->data.structVal->fields[i].id);
if (gv->data.structVal->fields[i].value.type == STRING) {
printf("\"");
printGroundValue(&gv->data.structVal->fields[i].value);
printf("\"");
} else {
printGroundValue(&gv->data.structVal->fields[i].value);
}
}
printf(" }>");
break;
}
case CUSTOM: {
printf("<object fields: { ");
for (size_t i = 0; i < gv->customType->size; i++) {
if (i != 0) {
printf(", ");
}
printf("%s: ", gv->customType->fields[i].id);
GroundObjectField* field = findField(*gv->data.customVal, gv->customType->fields[i].id);
if (field == NULL) {
printf("<missing>");
} else {
printGroundValue(&field->value);
}
}
printf(" }>");
break;
}
case ERROR: {
printf("<error type: %s, what: %s>", gv->data.errorVal.type, gv->data.errorVal.what);
break;
}
case NONE: {
printf("<none>");
break; break;
} }
} }
@@ -374,6 +413,12 @@ void printGroundInstruction(GroundInstruction* gi) {
case STOD: case STOD:
printf("stod"); printf("stod");
break; break;
case CTOI:
printf("ctoi");
break;
case ITOC:
printf("itoc");
break;
case TOSTRING: case TOSTRING:
printf("tostring"); printf("tostring");
break; break;

View File

@@ -9,7 +9,7 @@
#include "include/uthash.h" #include "include/uthash.h"
typedef enum GroundInstType { typedef enum GroundInstType {
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, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD 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, STOI, STOD, ITOC, CTOI, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD
} GroundInstType; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {

View File

@@ -1,3 +1,11 @@
tostring 32 &int tostring 32 &str
stoi "12" &int
stod "3.14" &dou
itoc 353 &chr
ctoi 'a' &it2
println $str
println $int println $int
println $dou
println $chr
println $it2