diff --git a/source/script/ABadIdeaVersion3.vcxproj b/source/script/ABadIdeaVersion3.vcxproj
index 2deb8e2..53eb1d3 100644
--- a/source/script/ABadIdeaVersion3.vcxproj
+++ b/source/script/ABadIdeaVersion3.vcxproj
@@ -145,6 +145,7 @@
+
diff --git a/source/script/ABadIdeaVersion3.vcxproj.filters b/source/script/ABadIdeaVersion3.vcxproj.filters
index b6dfa81..26caa24 100644
--- a/source/script/ABadIdeaVersion3.vcxproj.filters
+++ b/source/script/ABadIdeaVersion3.vcxproj.filters
@@ -87,6 +87,9 @@
Source Files\Classes\Elseable
+
+ Source Files\Classes\Dictionary
+
diff --git a/source/script/dictionaryClass.c b/source/script/dictionaryClass.c
new file mode 100644
index 0000000..242b141
--- /dev/null
+++ b/source/script/dictionaryClass.c
@@ -0,0 +1,50 @@
+#include "dictionaryClass.h"
+#include
+#include "garbageCollector.h"
+
+u8 dictOneStrOneAll[] = { StringClass, VARARGCOUNT };
+
+Dict_t* getEntry(Vector_t *v, char* name) {
+ vecForEach(Dict_t*, dict, v) {
+ if (!strcmp(name, dict->name)) {
+ return dict;
+ }
+ }
+ return NULL;
+}
+
+ClassFunction(dictSet) {
+ addPendingReference(args[1]);
+ char* arg = CpyStr(args[0]->string.value);
+ Dict_t* possibleEntry = getEntry(&caller->dictionary.vector, arg);
+ if (possibleEntry == NULL) {
+ Dict_t a = { .name = arg, .var = args[1] };
+ vecAdd(&caller->dictionary.vector, a);
+ }
+ else {
+ possibleEntry->var = args[1];
+ free(arg);
+ }
+ return &emptyClass;
+}
+
+ClassFunctionTableEntry_t dictFunctions[] = {
+ {"set", dictSet, 2, dictOneStrOneAll},
+};
+
+Variable_t getDictMember(Variable_t* var, char* memberName) {
+ if (!strcmp(memberName, "set"))
+ return getGenericFunctionMember(var, memberName, dictFunctions, ARRAY_SIZE(dictFunctions));
+
+ vecForEach(Dict_t*, dict, (&var->dictionary.vector)) {
+ if (!strcmp(dict->name, memberName)) {
+ Variable_t a = { 0 };
+ a.variableType = ReferenceType;
+ a.referenceType = dict->var;
+ addPendingReference(dict->var);
+ return a;
+ }
+ }
+
+ return (Variable_t) { 0 };
+}
\ No newline at end of file
diff --git a/source/script/dictionaryClass.h b/source/script/dictionaryClass.h
index 665b57c..8cb5361 100644
--- a/source/script/dictionaryClass.h
+++ b/source/script/dictionaryClass.h
@@ -1,3 +1,6 @@
#pragma once
#include "model.h"
#include "genericClass.h"
+#include "compat.h"
+
+Variable_t getDictMember(Variable_t* var, char* memberName);
\ No newline at end of file
diff --git a/source/script/eval.c b/source/script/eval.c
index 41a6f46..7de4649 100644
--- a/source/script/eval.c
+++ b/source/script/eval.c
@@ -187,6 +187,9 @@ void runtimeVariableEdit(Callback_SetVar_t* set, Variable_t* curRes) {
callMemberFunctionDirect(set->setVar, "set", args, 2);
}
+ removePendingReference(curRes);
+ removePendingReference(set->setVar);
+
// TODO: add non-top level sets
}
diff --git a/source/script/genericClass.c b/source/script/genericClass.c
index 56f082e..7b9b412 100644
--- a/source/script/genericClass.c
+++ b/source/script/genericClass.c
@@ -13,6 +13,7 @@
#include "saveClass.h"
#include "unsolvedArrayClass.h"
#include "else.h"
+#include "dictionaryClass.h"
Variable_t* copyVariableToPtr(Variable_t var) {
Variable_t* a = malloc(sizeof(Variable_t));
@@ -31,12 +32,12 @@ MemberGetters_t memberGetters[] = {
{SolvedArrayReferenceClass, getArrayReferenceMember},
{UnresolvedArrayClass, getUnsolvedArrayMember},
{ElseClass, getElseMember},
+ {DictionaryClass, getDictMember},
#ifndef WIN32
{SaveClass, getSaveMember},
#endif
};
-
Variable_t* genericGet(Variable_t* var, CallArgs_t* ref) {
if (ref->extraAction == ActionExtraMemberName) {
for (u32 i = 0; i < ARRAY_SIZE(memberGetters); i++) {
@@ -45,6 +46,10 @@ Variable_t* genericGet(Variable_t* var, CallArgs_t* ref) {
if (member.variableType == None)
return NULL;
+ if (member.variableType == ReferenceType) {
+ return member.referenceType;
+ }
+
addPendingReference(var); // So caller doesn't fall out of scope. Don't forget to free!
return copyVariableToPtr(member);
}
@@ -186,6 +191,7 @@ Variable_t* genericCall(Variable_t* var, CallArgs_t* ref) {
}
}
+// TODO: add staticStorage
Variable_t getGenericFunctionMember(Variable_t* var, char* memberName, ClassFunctionTableEntry_t* entries, u8 len) {
Variable_t newVar = {.readOnly = 1, .variableType = FunctionClass};
newVar.function.origin = var;
@@ -213,7 +219,12 @@ Variable_t* callMemberFunction(Variable_t* var, char* memberName, CallArgs_t* ar
if (funcRef.variableType == None)
return NULL;
- return genericCall(&funcRef, args);
+ Variable_t* ptr = &funcRef;
+ if (funcRef.variableType == ReferenceType) {
+ ptr = funcRef.referenceType;
+ }
+
+ return genericCall(ptr, args);
}
}
@@ -228,7 +239,12 @@ Variable_t* callMemberFunctionDirect(Variable_t* var, char* memberName, Variable
SCRIPT_FATAL_ERR("Did not find member '%s'", memberName);
}
- return genericCallDirect(&funcRef, args, argsLen);
+ Variable_t* ptr = &funcRef;
+ if (funcRef.variableType == ReferenceType) {
+ ptr = funcRef.referenceType;
+ }
+
+ return genericCallDirect(ptr, args, argsLen);
}
}
@@ -251,6 +267,13 @@ void freeVariableInternal(Variable_t* referencedTarget) {
case IntArrayClass:
vecFree(referencedTarget->solvedArray.vector);
break;
+ case DictionaryClass:;
+ vecForEach(Dict_t*, dict, (&referencedTarget->dictionary.vector)) {
+ modReference(dict->var, 0);
+ free(dict->name);
+ }
+ FREE(referencedTarget->dictionary.vector.data);
+ break;
}
}
diff --git a/source/script/model.h b/source/script/model.h
index db004aa..d2596d1 100644
--- a/source/script/model.h
+++ b/source/script/model.h
@@ -36,6 +36,7 @@ typedef enum {
SolvedArrayReferenceClass,
SaveClass,
ElseClass,
+ ReferenceType,
} VariableType_t;
typedef enum {
@@ -176,6 +177,7 @@ typedef struct _Variable_t {
#ifndef WIN32
SaveClass_t *save;
#endif
+ struct _Variable_t* referenceType;
};
union {
struct {
diff --git a/source/script/standardLibrary.c b/source/script/standardLibrary.c
index 084f57d..56d3818 100644
--- a/source/script/standardLibrary.c
+++ b/source/script/standardLibrary.c
@@ -79,6 +79,13 @@ ClassFunction(stdBreak) {
return NULL;
}
+ClassFunction(stdDict) {
+ Variable_t a = { 0 };
+ a.variableType = DictionaryClass;
+ a.dictionary.vector = newVec(sizeof(Dict_t), 0);
+ return copyVariableToPtr(a);
+}
+
#ifndef WIN32
ClassFunction(stdMountSysmmc){
if (connectMMC(MMC_CONN_EMMC))
@@ -121,6 +128,7 @@ enum standardFunctionIndexes {
STD_MOUNTSAVE,
STD_EXIT,
STD_BREAK,
+ STD_DICT,
};
u8 oneIntoneFunction[] = { IntClass, FunctionClass };
@@ -135,6 +143,7 @@ ClassFunctionTableEntry_t standardFunctionDefenitions[] = {
[STD_MOUNTSAVE] = {"readsave", stdMountSave, 1, oneStringArgStd},
[STD_EXIT] = {"exit", stdExit, 0, 0},
[STD_BREAK] = {"break", stdBreak, 0, 0},
+ [STD_DICT] = {"dict", stdDict, 0, 0},
};
ClassFunctionTableEntry_t* searchStdLib(char* funcName) {