Example #1
0
/**
 * CTRMessageSend
 *
 * Sends a message to a receiver object.
 */
ctr_object* ctr_send_message(ctr_object* receiverObject, char* message, long vlen, ctr_argument* argumentList) {
	char toParent = 0;
	ctr_object* me;
	ctr_object* methodObject;
	ctr_object* searchObject;
	ctr_argument* argCounter;
	ctr_argument* mesgArgument;
	ctr_object* result;
	ctr_object* (*funct)(ctr_object* receiverObject, ctr_argument* argumentList);
	int argCount;
	if (CtrStdError != NULL) return NULL; /* Error mode, ignore subsequent messages until resolved. */
	methodObject = NULL;
	searchObject = receiverObject;
	if (vlen > 1 && message[0] == '`') {
		me = ctr_internal_object_find_property(ctr_contexts[ctr_context_id], ctr_build_string_from_cstring("me\0"), 0);
		if (searchObject == me) {
			toParent = 1;
			message = message + 1;
			vlen--;
		}
	}
	while(!methodObject) {
		methodObject = ctr_internal_object_find_property(searchObject, ctr_build_string(message, vlen), 1);
		if (methodObject && toParent) { toParent = 0; methodObject = NULL; }
		if (methodObject) break;
		if (!searchObject->link) break;
		searchObject = searchObject->link;
	}
	if (!methodObject) {
		argCounter = argumentList;
		argCount = 0;
		while(argCounter->next && argCount < 4) {
			argCounter = argCounter->next;
			argCount ++;
		}
		mesgArgument = CTR_CREATE_ARGUMENT();
		mesgArgument->object = ctr_build_string(message, vlen);
		mesgArgument->next = argumentList;
		if (argCount == 0 || argCount > 2) {
			return ctr_send_message(receiverObject, "respondTo:", 10,  mesgArgument);
		} else if (argCount == 1) {
			return ctr_send_message(receiverObject, "respondTo:with:", 15,  mesgArgument);
		} else if (argCount == 2) {
			return ctr_send_message(receiverObject, "respondTo:with:and:", 19,  mesgArgument);
		}
	}
	if (methodObject->info.type == CTR_OBJECT_TYPE_OTNATFUNC) {
		funct = methodObject->value.fvalue;
		result = funct(receiverObject, argumentList);
	}
	if (methodObject->info.type == CTR_OBJECT_TYPE_OTBLOCK) {
		result = ctr_block_run(methodObject, argumentList, receiverObject);
	}	
	return result;
}
Example #2
0
/**
 * CTRFindInMy
 *
 * Tries to locate a property of an object.
 */
ctr_object* ctr_find_in_my(ctr_object* key) {
	ctr_object* context = ctr_find(ctr_build_string("me",2));
	ctr_object* foundObject = ctr_internal_object_find_property(context, key, 0);
	if (CtrStdError) return CtrStdNil;
	if (foundObject == NULL) { printf("Error, property not found: %s.\n", key->value.svalue->value); exit(1); }
	return foundObject;
}
Example #3
0
/**
 * @internal
 * 
 * Reads a server option set by user.
 */
ctr_object* ctr_request_internal_option(ctr_object* myself, char* optName) {
	ctr_object* key;
	ctr_object* val;
	key = ctr_build_string_from_cstring(optName);
	val = ctr_internal_object_find_property(myself, key, CTR_CATEGORY_PRIVATE_PROPERTY);
	return val;
}
Example #4
0
/**
 * [Map] at: [Key]
 *
 * Retrieves the value specified by the key from the map.
 *
 * In other languages:
 * Dutch: [Lijst] bij: [Object] | Geeft de waarde bij de bijbehorende sleutel.
 */
ctr_object* ctr_map_get(ctr_object* myself, ctr_argument* argumentList) {

	ctr_argument* emptyArgumentList;
	ctr_object*   searchKey;
	ctr_object*   foundObject;

	emptyArgumentList = ctr_heap_allocate(sizeof(ctr_argument));
	emptyArgumentList->next = NULL;
	emptyArgumentList->object = NULL;

	searchKey = argumentList->object;

	/* Give developer a chance to define a key for array */
	searchKey = ctr_send_message(searchKey, CTR_DICT_TOSTRING, strlen(CTR_DICT_TOSTRING), emptyArgumentList);
	ctr_heap_free( emptyArgumentList );

	/* If developer returns something other than string (ouch, toString), then cast anyway */
	if (searchKey->info.type != CTR_OBJECT_TYPE_OTSTRING) {
		searchKey = ctr_internal_cast2string(searchKey);
	}

	foundObject = ctr_internal_object_find_property(myself, searchKey, 0);
	if (foundObject == NULL) foundObject = ctr_build_nil();
	return foundObject;
}
Example #5
0
/**
 * [File] read
 *
 * Reads contents of a file. Send this message to a file to read the entire contents in
 * one go. For big files you might want to prefer a streaming approach to avoid
 * memory exhaustion (see readBytes etc).
 *
 * Usage:
 *
 * data := File new: '/path/to/mydata.csv', read.
 *
 * In the example above we read the contents of the entire CSV file callled mydata.csv
 * in the variable called data.
 */
ctr_object* ctr_file_read(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_object* str;
	ctr_size vlen, fileLen;
	char* pathString;
	char *buffer;
	FILE* f;
	if (path == NULL) return CtrStdNil;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate( sizeof(char) * ( vlen + 1 ) );
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "rb");
	ctr_heap_free( pathString );
	if (!f) {
		CtrStdFlow = ctr_build_string_from_cstring( "Unable to open file." );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	fseek(f, 0, SEEK_END);
	fileLen=ftell(f);
	fseek(f, 0, SEEK_SET);
	buffer=(char *)ctr_heap_allocate(fileLen+1);
	if (!buffer){
		printf("Out of memory\n");
		fclose(f);exit(1);	
	}
	fread(buffer, fileLen, 1, f);
	fclose(f);
	str = ctr_build_string(buffer, fileLen);
	ctr_heap_free( buffer );
	return str;
}
Example #6
0
/**
 * CTRFind
 *
 * Tries to locate a variable in the current context or one
 * of the contexts beneath.
 */
ctr_object* ctr_find(ctr_object* key) {
	int i = ctr_context_id;
	ctr_object* foundObject = NULL;
	if (CtrStdError) return CtrStdNil;
	while((i>-1 && foundObject == NULL)) {
		ctr_object* context = ctr_contexts[i];
		foundObject = ctr_internal_object_find_property(context, key, 0);
		i--;
	}
	if (foundObject == NULL) {
		ctr_internal_plugin_find(key);
		foundObject = ctr_internal_object_find_property(CtrStdWorld, key, 0);
	}
	if (foundObject == NULL) {
		char* cstr;
		CTR_2CSTR(cstr, key);
		printf("Error, key not found: [%s].\n", cstr);
		exit(1);
	}
	return foundObject;
}
Example #7
0
/**
 * [File] run
 *
 * Includes the file as a piece of executable code.
 */
ctr_object* ctr_file_include_ast(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string("path",4), 0);
	ctr_tnode* parsedCode;
	ctr_size vlen;
	char* pathString;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = malloc(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	parsedCode = ctr_serializer_unserialize(pathString);
	ctr_cwlk_run(parsedCode);
	return myself;
}
Example #8
0
/**
 * [File] delete
 *
 * Deletes the file.
 */
ctr_object* ctr_file_delete(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string("path",4), 0);
	ctr_size vlen;
	char* pathString;
	int r;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = malloc(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	r = remove(pathString);
	if (r!=0) {
		CtrStdError = ctr_build_string_from_cstring("Unable to delete file.\0");
		return CtrStdNil;
	}
	return myself;
}
Example #9
0
/**
 * [File] exists
 *
 * Returns True if the file exists and False otherwise.
 */
ctr_object* ctr_file_exists(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_size vlen;
	char* pathString;
	FILE* f;
	int exists;
	if (path == NULL) return ctr_build_bool(0);
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "r");
	ctr_heap_free( pathString );
	exists = (f != NULL );
	if (f) {
		fclose(f);
	}
	return ctr_build_bool(exists);
}
Example #10
0
/**
 * CTRSetBasic
 *
 * Sets a proeprty in an object (context).
 */
void ctr_set(ctr_object* key, ctr_object* object) {
	int i = ctr_context_id;
	ctr_object* context;
	ctr_object* foundObject = NULL;
	if (ctr_contexts[ctr_context_id] == CtrStdWorld) {
		ctr_internal_object_set_property(ctr_contexts[ctr_context_id], key, object, 0);
		return;
	}
	while((i>-1 && foundObject == NULL)) {
		context = ctr_contexts[i];
		foundObject = ctr_internal_object_find_property(context, key, 0);
		if (foundObject) break;
		i--;
	}
	if (!foundObject) {
		printf("Error, cannot assign, key not found: %s, forgot to use var ?\n", key->value.svalue->value); exit(1);
	}
	ctr_internal_object_set_property(context, key, object, 0);
}
Example #11
0
/**
 * [File] delete
 *
 * Deletes the file.
 */
ctr_object* ctr_file_delete(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_size vlen;
	char* pathString;
	int r;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate( sizeof( char ) * ( vlen + 1 ) );
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	r = remove(pathString);
	ctr_heap_free( pathString );
	if (r!=0) {
		CtrStdFlow = ctr_build_string_from_cstring( "Unable to delete file." );
		CtrStdFlow->info.sticky = 1;
		return CtrStdNil;
	}
	return myself;
}
Example #12
0
/**
 * BlockRun
 *
 * Runs a block of code.
 */
ctr_object* ctr_block_run(ctr_object* myself, ctr_argument* argList, ctr_object* my) {
	ctr_object* result;
	ctr_tnode* node = myself->value.block;
	ctr_tlistitem* codeBlockParts = node->nodes;
	ctr_tnode* codeBlockPart1 = codeBlockParts->node;
	ctr_tnode* codeBlockPart2 = codeBlockParts->next->node;
	ctr_tlistitem* parameterList = codeBlockPart1->nodes;
	ctr_tnode* parameter;
	ctr_object* a;
	ctr_open_context();
	if (parameterList && parameterList->node) {
		parameter = parameterList->node;
		while(1) {
			if (parameter && argList->object) {
				a = argList->object;
				ctr_assign_value_to_local(ctr_build_string(parameter->value, parameter->vlen), a);
			}
			if (!argList->next) break;
			argList = argList->next;
			if (!parameterList->next) break;
			parameterList = parameterList->next;
			parameter = parameterList->node;
		}
	}
	ctr_assign_value_to_local(ctr_build_string("me",2), my);
	ctr_assign_value_to_local(ctr_build_string("thisBlock",9), myself); /* otherwise running block may get gc'ed. */
	result = ctr_cwlk_run(codeBlockPart2);
	if (result == NULL) result = my;
	ctr_close_context();
	if (CtrStdError != NULL && CtrStdError != CtrStdNil) {
		ctr_object* catchBlock = malloc(sizeof(ctr_object));
		catchBlock = ctr_internal_object_find_property(myself, ctr_build_string("catch",5), 0);
		if (catchBlock != NULL) {
			ctr_argument* a = CTR_CREATE_ARGUMENT();
			a->object = CtrStdError;
			CtrStdError = NULL;
			ctr_block_run(catchBlock, a, my);
			result = myself;
		}
	}
	return result;
}
Example #13
0
/**
 * [File] include
 *
 * Includes the file as a piece of executable code.
 */
ctr_object* ctr_file_include(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	ctr_tnode* parsedCode;
	ctr_size vlen;
	char* pathString;
	char* prg;
	uint64_t program_size = 0;
	if (path == NULL) return myself;
	vlen = path->value.svalue->vlen;
	pathString = ctr_heap_allocate_tracked(sizeof(char)*(vlen+1)); //needed until end, pathString appears in stracktrace
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	prg = ctr_internal_readf(pathString, &program_size);
	parsedCode = ctr_cparse_parse(prg, pathString);
	ctr_heap_free( prg );
	ctr_cwlk_subprogram++;
	ctr_cwlk_run(parsedCode);
	ctr_cwlk_subprogram--;
	return myself;
}
Example #14
0
/**
 * [File] write: [String]
 *
 * Writes content to a file.
 */
ctr_object* ctr_file_write(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* str = ctr_internal_cast2string(argumentList->object);
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string("path",4), 0);
	FILE* f;
	ctr_size vlen;
	char* pathString;
	if (path == NULL) return CtrStdNil;
	vlen = path->value.svalue->vlen;
	pathString = malloc(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "wb+");
	free(pathString);
	if (!f) {
		CtrStdError = ctr_build_string_from_cstring("Unable to open file.\0");
		return CtrStdNil;
	}
	fwrite(str->value.svalue->value, sizeof(char), str->value.svalue->vlen, f);
	fclose(f);
	return myself;
}
Example #15
0
/**
 * [File] size
 *
 * Returns the size of the file.
 */
ctr_object* ctr_file_size(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string("path",4), 0);
	ctr_size vlen;
	char* pathString;
	FILE* f;
	int prev, sz;
	if (path == NULL) return ctr_build_number_from_float(0);
	vlen = path->value.svalue->vlen;
	pathString = malloc(vlen + 1);
	memcpy(pathString, path->value.svalue->value, vlen);
	memcpy(pathString+vlen,"\0",1);
	f = fopen(pathString, "r");
	if (f == NULL) return ctr_build_number_from_float(0);
	prev = ftell(f);
    fseek(f, 0L, SEEK_END);
    sz=ftell(f);
    fseek(f,prev,SEEK_SET);
    if (f) {
		fclose(f);
	}
    return ctr_build_number_from_float( (ctr_number) sz );
}
Example #16
0
/**
 * [File] open: [string]
 *
 * Open a file with using the specified mode.
 *
 * Usage:
 *
 * f := File new: '/path/to/file'.
 * f open: 'r+'. #opens file for reading and writing
 *
 * The example above opens the file in f for reading and writing.
 */
ctr_object* ctr_file_open(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* pathObj = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	char* mode;
	char* path;
	FILE* handle;
	ctr_resource* rs = ctr_heap_allocate(sizeof(ctr_resource));
	ctr_object* modeStrObj = ctr_internal_cast2string( argumentList->object );
	if ( myself->value.rvalue != NULL ) {
		ctr_heap_free( rs );
		CtrStdFlow = ctr_build_string_from_cstring( "File has already been opened." );
		CtrStdFlow->info.sticky = 1;
		return myself;
	}
	if ( pathObj == NULL ) return myself;
	path = ctr_heap_allocate_cstring( pathObj );
	mode = ctr_heap_allocate_cstring( modeStrObj );
	handle = fopen(path,mode);
	ctr_heap_free( path );
	ctr_heap_free( mode );
	rs->type = 1;
	rs->ptr = handle;
	myself->value.rvalue = rs;
	return myself;
}
Example #17
0
/**
 * [Percolator] brew
 * 
 * Tries to brew some delicious coffee.
 * To brew one cup of coffee the Percolator needs two cups of water
 * and one spoon of coffee grounds.
 *
 * Read the inline comments to learn how to extend Citrine!
 */
ctr_object* ctr_percolator_brew(ctr_object* myself, ctr_argument* argumentList) {
	
	/**
	 * Fetch the coffee property, note that the key is a Citrine String object.
	 */
	ctr_object* coffee = ctr_internal_object_find_property(
		myself,                                    /* owner object */
		ctr_build_string_from_cstring( "coffee" ), /* key object */
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	/**
	 * Fetch the water property.
	 */
	ctr_object* water = ctr_internal_object_find_property(
		myself,
		ctr_build_string_from_cstring( "water" ),
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	/**
	 * To access a value:
	 * 
	 * - numeric values reside in value.nvalue
	 * - boolean values reside in value.bvalue
	 * - array   values reside in value.avalue (see ctr_collection)
	 * - string  values reside in value.svalue (see ctr_string)
	 * - block   values reside in value.block  (see ctr_tnode)
	 * - native functions      in value.fvalue
	 */
	if (coffee->value.nvalue < 1) {
		return ctr_build_string_from_cstring( "No more coffee." );
	}
	
	if (water->value.nvalue < 2) {
		return ctr_build_string_from_cstring( "No more water." );
	}
	
	coffee->value.nvalue -= 1;
	water->value.nvalue -= 2;
	
	/**
	 * To set a property of an object, use
	 * the set_property function.
	 */
	ctr_internal_object_set_property(
		myself, 
		ctr_build_string_from_cstring( "coffee" ),
		coffee,
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	ctr_internal_object_set_property(
		myself, 
		ctr_build_string_from_cstring( "water" ),
		water,
		CTR_CATEGORY_PRIVATE_PROPERTY
	);
	
	return ctr_build_string_from_cstring( "Coffee!" );
}
Example #18
0
/**
 * [File] path
 *
 * Returns the path of a file. The file object will respond to this
 * message by returning a string object describing the full path to the
 * recipient.
 */
ctr_object* ctr_file_path(ctr_object* myself, ctr_argument* argumentList) {
	ctr_object* path = ctr_internal_object_find_property(myself, ctr_build_string_from_cstring( "path" ), 0);
	if (path == NULL) return CtrStdNil;
	return path;
}