From e1f292fe0da8fdc3095865ada7d8acb840a59f54 Mon Sep 17 00:00:00 2001 From: suchmememanyskill Date: Fri, 1 Jan 2021 18:30:51 +0100 Subject: [PATCH] [script] vector slicing, basic file functions new operators: vector(int, byte) - int -> works like py's list[0:-int] vector(int, byte) : int -> works like py's list[int:] new functions: fileRead, fileWrite, fileExists, bytesToStr --- Makefile | 2 +- source/fs/menus/filemenu.c | 2 ++ source/script/args.c | 19 +++++++++++++++++++ source/script/functions.c | 36 ++++++++++++++++++++++++++++++++++++ source/script/lexer.c | 16 ++++++++++++---- source/script/types.h | 3 ++- source/utils/vector.c | 15 ++++++++++----- source/utils/vector.h | 3 ++- 8 files changed, 84 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 8363ce5..c9eb6a4 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) #CUSTOMDEFINES += -DDEBUG ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES) +CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall -Wno-missing-braces $(CUSTOMDEFINES) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) ################################################################################ diff --git a/source/fs/menus/filemenu.c b/source/fs/menus/filemenu.c index 74b6f77..7299bf7 100644 --- a/source/fs/menus/filemenu.c +++ b/source/fs/menus/filemenu.c @@ -82,6 +82,8 @@ void RunScript(char *path, FSEntry_t entry){ ctx.script = runLexar(script, size); free(script); + dictVectorAdd(&ctx.varDict, newDict(CpyStr("_CWD"), (newVar(StringType, 0, .stringType = path)))); + printError(mainLoop(&ctx)); freeVariableVector(&ctx.varDict); diff --git a/source/script/args.c b/source/script/args.c index 005375c..0d30a55 100644 --- a/source/script/args.c +++ b/source/script/args.c @@ -343,6 +343,25 @@ Variable_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len, u8 sho vecAddElement(&res.vectorType, in); } } + ELIFT(Minus){ + if (val.integerType >= res.vectorType.count) + return ErrValue(ERRSYNTAX); + + res.vectorType.count -= val.integerType; + Vector_t newV = vecCopy(&res.vectorType); + freeVariable(res); + res.vectorType = newV; + res.free = 1; + } + ELIFT(Selector){ + if (val.integerType >= res.vectorType.count) + return ErrValue(ERRSYNTAX); + + Vector_t newV = vecCopyOffset(&res.vectorType, val.integerType); + freeVariable(res); + res.vectorType = newV; + res.free = 1; + } } else if (res.varType == StringType && val.varType == IntType){ if (localOpToken == Minus){ diff --git a/source/script/functions.c b/source/script/functions.c index ec977d0..5d28b55 100644 --- a/source/script/functions.c +++ b/source/script/functions.c @@ -6,6 +6,9 @@ #include #include "lexer.h" +#include +#include "../fs/fsutils.h" + #define scriptFunction(name) Variable_t name(scriptCtx_t *ctx, Variable_t *vars, u32 varLen) scriptFunction(funcIf) { @@ -76,10 +79,39 @@ scriptFunction(funcSetPixel){ return NullVar; } +scriptFunction(funcFileExists){ + return newVar(IntType, 0, FileExists(vars[0].stringType)); +} + +// Args: Str (Path) +scriptFunction(funcReadFile){ + u32 fSize = 0; + u8 *buff = sd_file_read(vars[0].stringType, &fSize); + if (buff == NULL) + return ErrVar(ERRFATALFUNCFAIL); + + Vector_t vec = vecFromArray(buff, fSize, sizeof(u8)); + return newVar(ByteArrayType, 1, .vectorType = vec); +} + +// Args: Str (Path), vector(Byte) (toWrite) +scriptFunction(funcWriteFile){ + return newVar(IntType, 0, sd_save_to_file(vars[1].vectorType.data, vars[1].vectorType.count, vars[0].stringType)); +} + +scriptFunction(funcByteToStr){ + char *str = calloc(vars[0].vectorType.count + 1, 1); + memcpy(str, vars[0].vectorType.data, vars[0].vectorType.count); + return newVar(StringType, 1, .stringType = str); +} + u8 fiveInts[] = {IntType, IntType, IntType, IntType, IntType}; u8 singleIntArray[] = { IntArrayType }; u8 singleInt[] = { IntType }; u8 singleAny[] = { varArgs }; +u8 singleStr[] = { StringType }; +u8 singleByteArr[] = { ByteArrayType }; +u8 StrByteVec[] = { StringType, ByteArrayType}; functionStruct_t scriptFunctions[] = { {"if", funcIf, 1, singleInt}, @@ -90,6 +122,10 @@ functionStruct_t scriptFunctions[] = { {"len", funcLen, 1, singleAny}, {"byte", funcMakeByteArray, 1, singleIntArray}, {"setPixel", funcSetPixel, 5, fiveInts}, + {"fileRead", funcReadFile, 1, singleStr}, + {"fileWrite", funcWriteFile, 2, StrByteVec}, + {"fileExists", funcFileExists, 1, singleStr}, + {"bytesToStr", funcByteToStr, 1, singleByteArr}, }; Variable_t executeFunction(scriptCtx_t* ctx, char* func_name, lexarToken_t *start, u32 len) { diff --git a/source/script/lexer.c b/source/script/lexer.c index bb9bf7c..9b5c4da 100644 --- a/source/script/lexer.c +++ b/source/script/lexer.c @@ -102,15 +102,19 @@ Vector_t runLexar(const char* in, u32 len) { // maybe measure len between ( ) and [ ], so this doesn't have to be done during runtime? // We also have to support (()). maybe if '(' set indent level, then if ')' minus indent level, set len. indent level contains {u8 level, u16 token, u16 startoffset} + u32 lastAssignment = 0; + while ((in - start) < len) { lexarToken_t* lx = vecGetArray(lexarToken_t*, vec); if ((lx[vec.count - 2].token == StrLit || lx[vec.count - 2].token == IntLit || lx[vec.count - 2].token == Variable || lx[vec.count - 2].token == RSBracket || lx[vec.count - 2].token == RBracket) && (lx[vec.count - 1].token == Variable || lx[vec.count - 1].token == LCBracket || lx[vec.count - 1].token == RCBracket)) { - lexarToken_t holder = lx[vec.count - 1]; - lx[vec.count - 1] = makeLexarToken(EquationSeperator, 0); - vecAddElement(&vec, holder); - lx = vecGetArray(lexarToken_t*, vec); + if (!(lx[lastAssignment].token == ArrayVariableAssignment && lx[vec.count - 1].token == Variable && lx[vec.count - 2].token == RSBracket)) { + lexarToken_t holder = lx[vec.count - 1]; + lx[vec.count - 1] = makeLexarToken(EquationSeperator, 0); + vecAddElement(&vec, holder); + lx = vecGetArray(lexarToken_t*, vec); + } } if (isValidWord(*in)) { @@ -170,8 +174,12 @@ Vector_t runLexar(const char* in, u32 len) { } if (lx[vec.count - back].token == ArrayVariable) { lx[vec.count - back].token = ArrayVariableAssignment; + lastAssignment = vec.count - back; + in++; + continue; } } + lastAssignment = 0; } ELIFC('{') { if (lx[vec.count - 1].token == VariableAssignment) { diff --git a/source/script/types.h b/source/script/types.h index 8c3f3f4..44bdb1b 100644 --- a/source/script/types.h +++ b/source/script/types.h @@ -57,7 +57,8 @@ enum Errors { ERRNOVAR, ERRNOFUNC, ERRINACTIVEINDENT, - ERRDIVBYZERO + ERRDIVBYZERO, + ERRFATALFUNCFAIL, }; enum Variables { diff --git a/source/utils/vector.c b/source/utils/vector.c index c0530f0..19f9c31 100644 --- a/source/utils/vector.c +++ b/source/utils/vector.c @@ -47,9 +47,14 @@ bool vecAdd(Vector_t* v, void* elem, u32 sz) return true; } -Vector_t vecCopy(Vector_t* orig) { - Vector_t dst = newVec(orig->elemSz, orig->count); - memcpy(dst.data, orig->data, orig->count * orig->elemSz); - dst.count = orig->count; +Vector_t vecCopyOffset(Vector_t* orig, u32 offset) { + Vector_t dst = newVec(orig->elemSz, orig->count - offset); + memcpy(dst.data, ((u8*)orig->data + orig->elemSz * offset), (orig->count - offset) * orig->elemSz); + dst.count = orig->count - offset; return dst; -} \ No newline at end of file +} + +Vector_t vecCopy(Vector_t* orig) { + return vecCopyOffset(orig, 0); +} + diff --git a/source/utils/vector.h b/source/utils/vector.h index b845773..19b0593 100644 --- a/source/utils/vector.h +++ b/source/utils/vector.h @@ -26,4 +26,5 @@ typedef struct { Vector_t newVec(u32 typesz, u32 preallocate); Vector_t vecFromArray(void* array, u32 count, u32 typesz); bool vecAdd(Vector_t* v, void* elem, u32 sz); -Vector_t vecCopy(Vector_t* orig); \ No newline at end of file +Vector_t vecCopy(Vector_t* orig); +Vector_t vecCopyOffset(Vector_t* orig, u32 offset); \ No newline at end of file