void startLexingFiles(Lexer *self, Vector *sourceFiles) { for (int i = 0; i < sourceFiles->size; i++) { SourceFile *sourceFile = getVectorItem(sourceFiles, i); // reset everything self->inputLength = strlen(sourceFile->fileContents); if (self->inputLength <= 0) { errorMessage("File `%s` is empty", sourceFile->name); self->failed = true; return; } self->input = sourceFile->fileContents; self->pos = 0; self->lineNumber = 1; self->charNumber = 1; self->currentChar = self->input[self->pos]; self->tokenStream = createVector(VECTOR_EXPONENTIAL); self->running = true; self->fileName = sourceFile->fileName; // get all the tokens while (self->running) { getNextToken(self); } // set the tokens to the current // token stream of the file being // lexed. sourceFile->tokens = self->tokenStream; } }
// allows us to evaluate user defined functions Value evalApply(Value expr, Frame *env) { // evaluate function Value f = eval(expr.consValue->car, env); if( (f.type != closureType) && (f.type != primitiveType) ){ return evaluationError("first argument of a function applcation did not evaluate to a proceedure"); } // evaluate arguments Vector args; initVector(&args,8); int i = 1; Value curr = getNth(expr.consValue, i); while(curr.type != openType){ Value *storedVal = (Value *)malloc(sizeof(Value)); (*storedVal) = valdup(eval(curr,env)); if((*storedVal).type == openType){ //This is an error void *pointerToAVal = NULL; for(int j = 0; j < i-2; j++){ getVectorItem(&args, j, &pointerToAVal); freeValue(*((Value *)pointerToAVal)); free((Value *)pointerToAVal); } free(storedVal); return evaluationError(NULL); } insertVectorItem(&(args), i-1, (void *)storedVal); i++; curr = getNth(expr.consValue, i); } // apply the function Value ret = apply(f, args); cleanupVector(&args); return ret; }
char* getTokenContext(Vector *stream, Token *tok) { sds result = sdsempty(); for (int i = 0; i < stream->size; i++) { Token *tempTok = getVectorItem(stream, i); if (tempTok->lineNumber == tok->lineNumber) { result = sdscat(result, tempTok->content); result = sdscat(result, " "); } } return result; }
/* Removes the Vectors and frees the Frame. */ void cleanupFrame(Frame *cleanMe){ if(!cleanMe) return; void *pointerToAValue = NULL; int vectorSize = cleanMe->values.size; for(int i = 0; i < vectorSize; i++){ getVectorItem(&(cleanMe->values),i,&pointerToAValue); freeValue(*((Value *)pointerToAValue)); free((Value *)pointerToAValue); } void *pointerToAChar = NULL; vectorSize = cleanMe->names.size; for(int i = 0; i < vectorSize; i++){ getVectorItem(&(cleanMe->names),i,&pointerToAChar); free((char *)pointerToAChar); } cleanupVector(&(cleanMe->names)); cleanupVector(&(cleanMe->values)); free(cleanMe); }
// Return the value of a variable Value resolveVar(Value expr, Frame *env){ if (env == NULL){ return evaluationError("symbol undefined in this context"); } int i = 0; void *pointerToAChar = NULL; //RIP pointerToACharstar while(getVectorItem(&(env->names), i, &pointerToAChar)){ if (strcmp( ((char *)pointerToAChar), expr.symbolValue) == 0){ void *pointerToAValue = NULL; if(!getVectorItem(&(env->values), i, &pointerToAValue)){ //This means we did frames wrong... return evaluationError("symbol was found, but does not correspond to a value"); } //This casts the return value to pointer an dereferences it. Value ret = *((Value *)pointerToAValue); return ret; } i++; } return resolveVar(expr, env->parent); }
// Allows us to apply userdefined functions Value apply(Value function, Vector args) { if (function.type == primitiveType) { void *pointerToAVal = NULL; for(int i = 0; i < args.size; i++){ getVectorItem(&args, i, &pointerToAVal); insertVectorItem(valGarbage, valGarbage->size, pointerToAVal); } return function.primitiveValue(args); } if (function.type == closureType) { Frame *newEnv = makeFrame(function.closureValue->env); Value formals = function.closureValue->formals; //check length Value shouldBeLast = getNth(formals.consValue, args.size-1); //should work if(args.size == 0) shouldBeLast.type = closeType; Value shouldNotExist = getNth(formals.consValue, args.size); //should fail if( (shouldBeLast.type == openType) || (shouldNotExist.type != openType) ){ return evaluationError("expected different number of args than recieved"); } // bind formals to actuals for(int i = 0; i < args.size; i++){ Value sym = getNth(formals.consValue, i); void *storedVal = NULL; getVectorItem(&args, i, &storedVal); insertVectorItem(&(newEnv->names), 0, (void *)strdup(sym.symbolValue)); insertVectorItem(&(newEnv->values), 0, (void *)storedVal); } insertVectorItem(envGarbage, envGarbage->size, (void *)newEnv); return eval(function.closureValue->body, newEnv); } // Else, error return evaluationError("apply called on non-function"); }
void destroyLexer(Lexer *self) { if (self->tokenStream != NULL) { for (int i = 0; i < self->tokenStream->size; i++) { Token *tok = getVectorItem(self->tokenStream, i); // eof's content isnt malloc'd so free would give us some errors if (tok->type != TOKEN_END_OF_FILE) { verboseModeMessage("Freed `%s` token", tok->content); sdsfree(tok->content); } destroyToken(tok); } } verboseModeMessage("Destroyed lexer"); free(self); }
// Adds bindings to a frame. Used in letrec bool addBindingsRec(Frame *theEnv, Value bindings) { // add things ConsCell *cc = bindings.consValue; int i = 0; while(cc){ if( cc->car.type != consType){ return false; } ConsCell *binding = cc->car.consValue; Value caar = getNth(binding,0); Value cadar = falseVal(); if( (caar.type == openType) || (cadar.type == openType) ){ return false; } Value *storedVal = (Value *)malloc(sizeof(Value)); (*storedVal) = valdup(cadar); insertVectorItem(&(theEnv->names), i, (void *)strdup(caar.symbolValue)); insertVectorItem(&(theEnv->values), i, (void *)storedVal); cc = cc->cdr.consValue; i++; } cc = bindings.consValue; i = 0; while(cc){ ConsCell *binding = cc->car.consValue; Value caar = getNth(binding,0); Value cadar = getNth(binding,1); if( (caar.type == openType) || (cadar.type == openType) ){ return false; } Value evaled = eval(cadar,theEnv); if( (evaled).type == openType){ return false; } void *theEggman = NULL; getVectorItem(&(theEnv->values), i, &theEggman); *(Value *) theEggman = evaled; cc = cc->cdr.consValue; i++; } return true; }