Display parseEval source in error messages.

This commit is contained in:
Sage Vaillancourt 2022-10-25 13:21:04 -04:00
parent b03d4cbd3f
commit 672cdb692a
8 changed files with 107 additions and 55 deletions

View File

@ -476,7 +476,7 @@ Object help(Object* params, int length, struct Environment* env)
int runTest(const char* test, const char* expected, int detailed)
{
struct Environment env = defaultEnv();
Object o = parseEval(test, &env);
Object o = parseEval(test, "testCode", &env);
size_t length;
char* result = stringObj(&o, &length);
cleanObject(&o);

View File

@ -116,7 +116,7 @@ void repl(struct Environment* env)
free(oldBuf);
}
Object o = parseEval(buf, env);
Object o = parseEval(buf, "REPL", env);
if (isFuncy(o) || isError(o, DID_NOT_FIND_SYMBOL)) {
system(buf);
} else {
@ -246,9 +246,9 @@ int main(int argc, const char* argv[])
readFile(SCRIPTDIR "/lib.pbl", &env);
}
Object o = parseEval("(def prompt %%)", &env);
Object o = parseEval("(def prompt %%)", "[INTERNAL]", &env);
cleanObject(&o);
o = parseEval("(def preprocess (fn (text) (text)))", &env);
o = parseEval("(def preprocess (fn (text) (text)))", "[INTERNAL]", &env);
cleanObject(&o);
if (!settings.ignoreConfig) {
@ -268,10 +268,10 @@ int main(int argc, const char* argv[])
if (file) {
// Execute a file
loadArgsIntoEnv(argc, argv, &env);
_readFile(file, &env);
_readFile(file, argv[argc - 1], &env);
} else {
// Run arguments directly as pl code
Object r = parseEval(argv[argc - 1], &env);
Object r = parseEval(argv[argc - 1], "[PL ARGUMENTS]", &env);
printAndClean(&r);
}
} else {

View File

@ -315,8 +315,11 @@ Object errorWithAllocatedContextLineNo(enum errorCode code, char* context, int l
#define errorAddContext(x, y, z, a) ;
#define throw(_code, ...) return errorObject(_code)
#else
#define throw(_code, ...) do { char* ERROR_CONTEXT = malloc(sizeof(char) * ERR_LEN); sprintf(ERROR_CONTEXT, __VA_ARGS__); \
return errorWithAllocatedContextLineNo(_code, ERROR_CONTEXT, __LINE__, __FILE__); } while (0)
#define throw(_code, ...) do { \
char* ERROR_CONTEXT = malloc(sizeof(char) * ERR_LEN); \
sprintf(ERROR_CONTEXT, __VA_ARGS__); \
return errorWithAllocatedContextLineNo(_code, ERROR_CONTEXT, __LINE__, __FILE__); \
} while (0)
#define errorWithContext(_code, _context) errorWithContextLineNo(_code, _context, __LINE__, __FILE__)
#endif

View File

@ -565,13 +565,13 @@ struct Slice* getLastOpen()
return lastOpen;
}
Object parseEval(const char* input, struct Environment* env)
Object parseEval(const char* input, const char* codeSource, struct Environment* env)
{
struct Error err = noError();
struct Slice* tokens = nf_tokenize(input, &err);
if (err.context != NULL) {
Object o = errorWithContext(err.code, err.context);
Object o = errorWithContextLineNo(err.code, err.context, err.plContext->lineNumber, codeSource);
free(err.context);
return o;
}
@ -681,21 +681,21 @@ char* readFileToString(FILE* input)
}
/// Returns 1 if the file could not be opened. Otherwise, 0
int readFile(const char* filename, struct Environment* env)
int readFile(const char* fileName, struct Environment* env)
{
FILE* input = fopen(filename, "r");
FILE* input = fopen(fileName, "r");
if (!input) {
return 1;
}
_readFile(input, env);
_readFile(input, fileName, env);
return 0;
}
int _readFile(FILE* input, struct Environment* env)
int _readFile(FILE* input, const char* fileName, struct Environment* env)
{
char* fileText = readFileToString(input);
fclose(input);
Object r = parseEval(fileText, env);
Object r = parseEval(fileText, fileName, env);
cleanObject(&r);
free(fileText - 1);

View File

@ -27,7 +27,7 @@ Result readSeq(struct Slice* slices);
Result parseAtom(struct Slice* slice);
Object parseEval(const char* input, struct Environment* env);
Object parseEval(const char* input, const char* fileName, struct Environment* env);
Object evalList(const Object* obj, struct Environment* env);
@ -57,9 +57,9 @@ if (FAILED) { \
char* readFileToString(FILE* input);
int _readFile(FILE* input, struct Environment* env);
int _readFile(FILE* input, const char* fileName, struct Environment* env);
int readFile(const char* filename, struct Environment* env);
int readFile(const char* fileName, struct Environment* env);
struct Slice* getLastOpen();

View File

@ -176,14 +176,14 @@ Object parseEvalO(Object* params, unused int length, struct Environment* env)
switch (text.type) {
case TYPE_SYMBOL: {
Object string = eval(&text, env);
Object parsed = parseEval(string.string, env);
Object parsed = parseEval(string.string, "(eval)", env);
cleanObject(&string);
return parsed;
}
case TYPE_SLIST:
return evalList(&text, env);
case TYPE_STRING:
return parseEval(text.string, env);
return parseEval(text.string, "(eval)", env);
default:
throw(CAN_ONLY_EVAL_STRINGS, "Tried to (eval) a %s, instead of a string or symbol list",
getTypeName(&text));
@ -329,7 +329,7 @@ int timeStructDefinition = -1;
Object getTime(unused Object* params, unused int length, struct Environment* env)
{
if (timeStructDefinition == -1) {
parseEval("(struct Time (minute hour sec))", env);
parseEval("(struct Time (minute hour sec))", "[INTERNAL]", env);
timeStructDefinition = getStructIndex("Time");
}
time_t t = time(NULL);

View File

@ -59,7 +59,7 @@ add_query_param(void* queryParamsV, enum MHD_ValueKind kind, const char* key,
Object pair = startList(nullTerminated(key));
Object parsed;
if (isDigit(value[0])) {
parsed = parseEval(value, NULL);
parsed = parseEval(value, "[INTERNAL]", NULL);
} else {
parsed = stringFromSlice(value, strlen(value));
}
@ -127,8 +127,7 @@ void initialize()
if (!initialized) {
initialized = 1;
}
eprintf("Initializing...\n");
Object o = parseEval("(struct Request (queryParams username password))", global());
Object o = parseEval("(struct Request (queryParams username password))", "[INTERNAL]", global());
cleanObject(&o);
requestDefinition = getStructIndex("Request");
}

View File

@ -4,17 +4,55 @@
/*
* Grammar:
* token
* expr
* (op expr expr)
* (list expr expr ... )
* Number:
* Hex:
* 0x[0-9a-f]+
* Bin:
* 0b[01]+
* Dec:
* -?[0-9]+
*
* String:
* "([^\n"])|(\\")*"
* """.*"""
*
* Boolean:
* T
* F
*
* List:
* (...Expression)
*
* SList:
* '(...Expression)
*
* Symbol:
* [a-z][a-z0-9]*
*
* Primitive:
* Symbol
* Number
* String
* Boolean
* List
*
* Function Call:
* (Symbol ...Expression)
*
* Struct Access:
* Symbol.Symbol
*
* Expression:
* Primitive
* Function Call
* Struct Access
*/
// Is the char a standalone token?
static const char singleTokens[] = "()'?";
int isSingle(const char *c)
{
static const char singleTokens[] = "()'?";
int i = 0;
while (singleTokens[i] != '\0') {
if (singleTokens[i] == c[0]) {
@ -39,18 +77,18 @@ int isWhitespace(const char c)
return c == ' ' || c == '\t' || c == '\n';
}
void buildErrFromInput(struct Error* err, enum errorCode code, int i, const char* input)
void buildErrFromInput(struct Error* err, enum errorCode code, int i, const char* input, struct Slice* slice)
{
err->context = malloc(sizeof(char) * ERR_LEN + 1);
err->code = code;
err->plContext = slice;
int start = i > ERR_LEN ? i - ERR_LEN : 0;
strncpy(err->context, &input[start], ERR_LEN);
}
void collectSymbol(const char* input, int* i, int* length);
void processString(const char* input, struct Error* err, struct Slice* slices, int slice, int* i, int* lineNumber,
int* length);
void processString(const char* input, struct Error* err, struct Slice* slice, int* i, int* lineNumber, int* length);
struct Slice* nf_tokenize(const char* input, struct Error* err)
{
@ -60,6 +98,7 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
}
struct Slice slices[MAX_TOK_CNT];
struct Slice* slice = &slices[0];
//int token_count = MAX_TOK_CNT;
// do {
// slices = malloc(sizeof(struct Slice) * token_count);
@ -67,7 +106,6 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
// } while (slices == NULL);
int i = 0;
int slice = 0;
int lineNumber = 1;
int parens = 0;
@ -86,14 +124,14 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
} else if (input[i] == ')') {
parens--;
if (parens < 0) {
buildErrFromInput(err, MISMATCHED_PARENS, i, input);
buildErrFromInput(err, MISMATCHED_PARENS, i, input, slice);
//free(slices);
return NULL;
}
}
slices[slice].text = &input[i];
slices[slice].lineNumber = lineNumber;
slice->text = &input[i];
slice->lineNumber = lineNumber;
if (isSingle(&input[i])) {
i++;
@ -103,28 +141,31 @@ struct Slice* nf_tokenize(const char* input, struct Error* err)
}
continue;
} else if (input[i] == '"') {
processString(input, err, slices, slice, &i, &lineNumber, &length);
processString(input, err, slice, &i, &lineNumber, &length);
if (err->context != NULL) {
return NULL;
}
} else {
collectSymbol(input, &i, &length);
if (length == 0) {
buildErrFromInput(err, BAD_SYMBOL, i, input, slice);
return NULL;
}
}
if (err->context != NULL) {
return NULL;
}
slices[slice].length = length;
slice->length = length;
slice++;
}
if (parens != 0) {
buildErrFromInput(err, MISMATCHED_PARENS, i, input);
buildErrFromInput(err, MISMATCHED_PARENS, i, input, slice);
//free(slices);
return NULL;
}
slices[slice].text = NULL;
slices[slice].length = 0;
size_t size = sizeof(struct Slice) * (slice + 1);
slice->text = NULL;
slice->length = 0;
size_t size = sizeof(struct Slice) * ((slice - &slices[0]) + 1);
struct Slice* allocated = malloc(size);
memcpy(allocated, slices, size);
@ -136,20 +177,28 @@ void singleQuotedString(const char* input, int* i, int* lineNumber, int* length)
void tripleQuotedString(const char* input, struct Error* err, struct Slice* slice, int* i, int* lineNumber,
int* length);
void processString(const char* input, struct Error* err, struct Slice* slices, int slice, int* i, int* lineNumber,
int* length)
void processString(const char* input, struct Error* err, struct Slice* slice, int* i, int* lineNumber, int* length)
{
if (input[(*i) + 1] == '"' && input[(*i) + 2] == '"') {
tripleQuotedString(input, err, &slices[slice], i, lineNumber, length);
tripleQuotedString(input, err, slice, i, lineNumber, length);
} else {
singleQuotedString(input, i, lineNumber, length);
}
(*i)++;
}
int validSymbolChar(const char* c)
{
return !isWhitespace(*c)
&& !isSingle(c)
&& *c != '"'
&& *c != '\0';
}
void collectSymbol(const char* input, int* i, int* length)
{
while (!isWhitespace(input[++(*i)]) && !isSingle(&input[(*i)]) && input[(*i)] != '"' && input[(*i)] != '\0') {
// TODO: Error if length is 0?
while (validSymbolChar(&input[++(*i)])) {
(*length)++;
}
}
@ -171,7 +220,7 @@ void tripleQuotedString(const char* input, struct Error* err, struct Slice* slic
}
(*length)++;
if (input[c] == '\0' || input[c + 1] == '\0' || input[c + 2] == '\0') {
buildErrFromInput(err, UNEXPECTED_EOF, c, input);
buildErrFromInput(err, UNEXPECTED_EOF, c, input, slice);
return;
}
}
@ -180,9 +229,10 @@ void tripleQuotedString(const char* input, struct Error* err, struct Slice* slic
void singleQuotedString(const char* input, int* i, int* lineNumber, int* length)
{
while (input[++(*i)] != '\0') {
if (input[(*i)] == '"') {
const int c = *i;
if (input[c] == '"') {
int backslashes = 0;
while (input[((*i) - 1) - backslashes] == '\\') {
while (input[(c - 1) - backslashes] == '\\') {
backslashes++;
}
// \\\" => Odd number of backslashes, quote IS escaped
@ -190,7 +240,7 @@ void singleQuotedString(const char* input, int* i, int* lineNumber, int* length)
if (backslashes % 2 == 0) {
break;
}
} else if (input[(*i)] == '\n') {
} else if (input[c] == '\n') {
(*lineNumber)++;
}
(*length)++;