summaryrefslogblamecommitdiff
path: root/doc/objects.txt
blob: 956ad743a2076aaf522312dc971d8334c63bcece (plain) (tree)




















































































































































































                                                                                                                     
Let me say this in french. Sorry for english-only-speaking people, i'll translate someday.

L'idée principale motivant le développement de T/CE est celle d'un nouveau protocole entre le
noyau et les applications utilisateur.

Les objets du systèmes sont accessibles sous la forme d'un système de fichiers dans lequel on
navigue, sauf que les objets sont en fait bien plus que de simples fichiers.

Ce protocole se base sur trois définitions fondamentales :
-- Interfaces :
Une interface est un ensemble de définitions (de prototypes, donc) de méthodes qui
peuvent être implémentées par un objet du système.
Parmi les méthodes, il y a des méthodes publiques, faites pour être appellées par les
applications utilisateurs, et des méthodes internes au noyau.
-- Classe :
Une classe, c'est un regroupement d'interfaces avec leur implémentation spécifique.
-- Objet :
Un objet du système est d'une classe précise, et correspond donc à un des objets gérés
par le code de cette classe. On peut appeller toutes les méthodes des interfaces implémentées
par la classe de l'objet sur cet objet.

Ce n'est peut-être pas très clair, alors illustrons :

Interface : Keyboard
- OutputToConsole(Console)
Interface : Console
- SetActiveVT (VirtualTerminal)
- NewBufferedVT (char*)						// crée un nouveau terminal virtuel - char* = le nom
- (internal) receiveKeyboardInput(int)
- (internal) repaint(char*)
- (internal) write(int, char*)
Interface : VirtualTerminal
- Read(int, char*)
- Write(int, char*)
- (internal) receiveKeyboardInput(int)
- (internal) outputToConsole(Console, int, int)	// int, int = dimensions de la console

Classe : PS2Keyboard
- Garde en mémoire la console à qui il envoie les données
- Quand une touche est pressée/relâchée, appeller receiveKeyboardInput sur cette console
- Implémenter la méthode OutputToConsole pour changer la console à qui les données sont envoyées
Classe : TextConsole
- Implémente la gestion de l'écran texte VGA de base
- Garde en mémoire le VirtualTerminal actif
- Transmet l'entrée clavier au VirtualTerminal actif
- Lorsqu'on lui demande de changer le VT actif :
    il signale à l'ancien VT de ne plus émettre,
	il signale au nouveau VT d'émettre vers cette console
		et spécifie au nouveau VT la bonne dimension d'écran
Classe : BufferedVirtualTerminal
- Il garde en mémoire LA Console vers laquelle il doit émettre, ainsi que ses dimensions
- Garde un buffer de tout ce qui passe sur la console, et un buffer de l'écran actif.
- Lorsqu'il reçoit une entrée clavier, la bufferise, puis la restitue lors du prochain appel à Read
- Lorsqu'on écrit quelque chose dessus avec Write, il le garde dans son buffer
		et le donne aussi au terminal virtuel de sortie, s'il y en a un


Implémentation :

// Structures

struct Interface {
	char* name;
	int method_count;
	int public_method_count;

	NumberedMethod numberedMethods[];
	int methodNumbers[];
};

struct NumberedMethod {
	Interface *iface;
	int numberInIface;
};

type MethodPtr (function pointer type);

struct InterfaceImpl {
	Interface *interface;
	MethodPtr methods[];
};

struct Class {
	char* name;
	MethodPtr *findChild;
	InterfaceImpl interfaces[];		//zero-terminated list
};

struct Object {
	Class *class;
	void *data;
};

// setup code

void Class_setup(Class* class) {
	for (int i = 0; class->interfaces[i] != 0; i++) {
		Interface_setup(class->interfaces[i]->interface)
	}
}

ExpandableTable<NumberedMethod*> allMethods;

void Interface_setup(Interface* iface) {
	if (iface->numberedMethods != 0) return;
	iface->numberedMethods = malloc(iface->method_count * sizeof(NumberedMethod));
	iface->methodNumbers = malloc(iface->method_count * sizeof(int));
	
	for (int i = 0; i < iface->method_count; i++) {
		iface->methodNumbers[i] = allMethods.register(&impl->numberedMethods[i])
		iface->numberedMethods[i]->numberInIface = i;
		iface->numberedMethods[i]->ptr = impl->methods[i];
	}
}

void Object_callByNumber(Object *obj, int number, params...) {
	NumberedMethod *method = allMethods.get(number);
	for (int i = 0; obj->class->interfaces[i] != 0; i++) {
		InterfaceImpl impl = obj->class->interfaces[i];
		if (method->iface == impl->interface) {
			MethodPtr fct = impl->methods[method->numberInIface];
			return fct (params...)
		}
	}
	return E_NOT_IMPLEMENTED;
}

// Exemple

struct ConsoleMethods {
	MethodPtr SetActiveVT;
	MethodPtr NewBufferedVT;
	MethodPtr receiveKeyboardInput;
	MethodPtr repaint;
	MethodPtr write;
};

Interface ConsoleIface = {
	name: "Console",
	method_count: 5,
	public_method_count: 2,

	numberedMethods: 0, methodNumbers: 0,	// internal
};

ConsoleMethods TextConsole_as_Console = {
	SetActiveVT: TextConsole_SetActiveVT,
	NewBufferedVT: TextConsole_NewBufferedVT,
	receiveKeyboardInput: TextConsole_receiveKeyboardInput,
	repaint: TextConsole_repaint,
	write: TextConsole_write,
};

Class TextConsoleClass = {
	name: "TextConsole",
	findChild: Console_findChild,
	interfaces: {
		{ ConsoleIface, (MethodPtr*)TextConsole_as_Console },
		0
	},
};

struct TextConsole {
	Object object;

	//... data ...
};

// Other example

struct FolderMethods {
	MethodPtr GetChildList;
};

Interface FolderIface = {
	name: "Folder",
	method_count: 1,
	public_method_count: 1,

	numberedMethods: 0, methodNumbers: 0,	// internal
};