Example #1
0
/**
 * Frees a compiler object and all associated memory.
 * compiler: an instance of Compiler.
 * TODO: a lot of allocations don't have frees yet. These will be added in when
 * the program structure becomes final.
 */
void compiler_free(Compiler * compiler) {
  assert(compiler != NULL);

  if(compiler->compiledScripts != NULL) {
    set_free(compiler->compiledScripts);
  }

  if(compiler->symTableStk != NULL) {
    stk_free(compiler->symTableStk);
  }

  if(compiler->functionHT != NULL) {
    HTIter htIterator;
    ht_iter_get(compiler->functionHT, &htIterator);

    while(ht_iter_has_next(&htIterator)) {
      DSValue value;
      ht_iter_next(&htIterator, NULL, 0, &value, NULL, true);
      compilerfunc_free(value.pointerVal);
    }

    ht_free(compiler->functionHT);
  }
 
  if(compiler->outBuffer != NULL) {
    buffer_free(compiler->outBuffer);
  }

  free(compiler);
}
Example #2
0
/**
 * Run after gunderscript_build_file() to export the compiled bytecode to an
 * external bytecode file.
 * instance: a Gunderscript object.
 * fileName: The name of the file to export to. Caution: file will be overwritten
 * returns: true upon success, or false if file cannot be opened, 
 * no code has been built, or there was an error building code.
 */
GSAPI bool gunderscript_export_bytecode(Gunderscript * instance, char * fileName) {
  FILE * outFile = fopen(fileName, "w");
  GSByteCodeHeader header;
  HTIter functionHTIter;
  char * byteCodeBuffer;

  /* check if file open fails */
  if(outFile == NULL) {
    instance->err = GUNDERSCRIPTERR_BAD_FILE_OPEN_WRITE;
    return false;
  }

  /* create header */
  strcpy(header.header, GS_BYTECODE_HEADER);
  strcpy(header.buildDate, __DATE__);
  header.byteCodeLen = vm_bytecode_size(instance->vm);
  header.numFunctions = ht_size(vm_functions(instance->vm));

  /* write header to file, return false on failure */
  if(fwrite(&header, sizeof(GSByteCodeHeader), 1, outFile) != 1) {
    instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE;
    return false;
  }
  
  ht_iter_get(vm_functions(instance->vm), &functionHTIter);

  /* write exported functions to file */
  while(ht_iter_has_next(&functionHTIter)) {
    DSValue value;
    char functionName[GS_MAX_FUNCTION_NAME_LEN];
    size_t functionNameLen;
    char outLen;

    /* get the next item from hashtable */
    ht_iter_next(&functionHTIter, functionName, GS_MAX_FUNCTION_NAME_LEN,
		 &value, &functionNameLen, false);

    /* check if the function should be exported. if so, write it to the file */
    if(((VMFunc*)value.pointerVal)->exported) {

      /* TODO: create an error handler case for this */
      assert(functionNameLen < GS_MAX_FUNCTION_NAME_LEN);
    
      /* write it's name and length to the file */
      outLen = functionNameLen;
      if(fwrite(&outLen, sizeof(char), 1, outFile) != 1 
	 || fwrite(functionName, sizeof(char), functionNameLen, outFile) 
	 != functionNameLen) {
	instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE;
	return false;
      }

      /* write its CompilerFunc to the file (stores function call information) */
      if(fwrite(value.pointerVal, sizeof(VMFunc), 1, outFile) != 1) {
	instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE;
	return false;
      }
    }
  }

  byteCodeBuffer = vm_bytecode(instance->vm);
  if(byteCodeBuffer == NULL) {
    instance->err = GUNDERSCRIPTERR_NO_SUCCESSFUL_BUILD;
    return false;
  }

  /* write bytecode */
  if(fwrite(byteCodeBuffer, 
	    vm_bytecode_size(instance->vm), 1, outFile) != 1) {
    instance->err = GUNDERSCRIPTERR_BAD_FILE_WRITE;
    return false;
  }

  fclose(outFile);

  return true;
}