Tenshi C

Tenshi C or TenC is an esolang created by User:Richard565
This language is an implementation of a small subset of C to work on a custom runtime(A move architecture instruction set) he wrote in JavaScript. He named it after the song from K-ON! tenshi ni fureta yo.
==History==
Originally he had planned to write a C compiler for his 24 bit CPU. 
But he believed that it was not satisfactory and so came of it Tenshi C. 
The runtime and simple compiler that comes with Tenshi C created was originally meant for his portfolio but it didn't work out.
The original intent was to make a simple Operating System with as few C features as possible or tolerable.
While the language is usable for Operating system development. It is not recommended. 
==Features and Quirks==
The most notable difference between Tenshi C and regular C is it's pointers. The pointers do not increment automatically by the size of a type.
Also pointers are dereferenced differently.
//regular C
int * s = (int*) (5+1); //s=9
*s // normal dereference
*((int*)s) // normal dereference
*s = 0; // sets memory at s to 0
//Tenshi C
WORD s = (WORD) (5+1); //s=6
((WORD)*s) // dereferences a word of data which is 28 bits
((BYTE)*s) // dereferences a byte of data which is 8 bits
((DBYTE)*s) //dereferences 16 bits
(WORD) *(s) = 0; //sets memory location at s which stores a memory location to 0
//WORD is the size of a pointer and can be treated as a pointer varible
A WORD is 28 bits
A DBYTE is 16 bits
A BYTE is 8 bits
==What's not implemented==
These are features omitted to keep the language more simple or they where omitted out of laziness.
 
 switch and do while loops
 error correction: Open the console for errors. Error's have not been fully implemented
 array's(there is a different syntax that is used)
 enums,typedef and macros(# is used for a different type of syntax)
 
==Examples==
===Hello world===
//an example hello world without libc
BYTE hello_world ="Hello World!!!"; // a varible storing the string
WORD main(){
 WORD s = 0;
 
 while( (BYTE) * (s+$hello_world) != 0 ){ // loops through hello_world and writes it to the MMIO screen.
 (BYTE) *(s) = (BYTE) * (s + $hello_world);
 s=s+1; 
 }
}
===Alternate Hello world===
//an example hello world without libc
WORD main(){
 WORD hello_world ="Hello World!!!"; // a pointer to a varible storing the string
 WORD s = 0;
 
 while( (BYTE) * (s+hello_world) != 0 ){ // loops through hello_world and writes it to the MMIO screen.
 (BYTE) *(s) = (BYTE) * (s + hello_world);
 s=s+1; 
 }
}
==Tutorial==
This tutorial is meant for those who have some experience with C. 
===Sizes===
 BYTE 8 bits
 DBYTE 16 bits
 WORD 28 bits(Per the limits of base javascript)
===Varibles===
WORD global_var = 0;// hello I'm a global varible
WORD main(){
 DBYTE local_var = 0; // hello I'm a local varible 
}
===Expressions===
//you cannot use Expressions to declare varibles in the global scope.
//all bitwise instructions are in the same presedence as multiplication and division
WORD main(){
 WORD i = 7;
 WORD local_var = (50+2*i)-3; //an example of an expression 
 WORD sd = asm_d("PSH 90"); // an example of an assembly block being used as an expression. The last thing pushed on the stack will actually be the result. So sd = 90
}
===Structures===
//structs are basically offsets to a pointer to acces data
struct person{
 WORD name;
 WORD bounty;
}
WORD main(){
 (struct person) 0x501.name = "Arlong";
 (struct person) 0x501.bounty = 20000000;
}
===Conditions and loops===
//there's no switch statements yet
//there is not a && or a || because booleans are expressions in assembly it's only a single comaprision
WORD main(){
 if(1==1){
 //do what's inside
 }else if(1==1){
 //do what's inside
 }else{
 //do what's inside
 }
 for(WORD s =0; s< 90; s++){
 //do whats inside
 }
 WORD s = 0;
 while(s<90){
 //no "+="
 s++;
 } 
}
===Functions,Subroutines, Procedures===
WORD main(){
 
print_z(return_nine()); // prints a Z at the nineth position.
}
//Functions can be marked WORD,BYTE,DBYTE but the lanugage ignores this. It's more like a label.
//All functions don't need to return a value.
// all parameters are words
WORD return_nine(){
 
 return 9;
}
WORD print_z(WORD where){
 (BYTE) *(where) = 90;
}
====Function pointers====
WORD write_z(){
 (BYTE) *(0) = 90;
}
WORD main(){
 WORD func_ptr = $write_z; // can only call functions above them because it is a one pass on memory counter
 #fup (func_ptr).(); // #fup is the function pointer call. 
}
===What libC includes===
// This is the small libC that comes with the implementation
//you must copy and paste this bellow the main program
BYTE strcmp(WORD str,WORD strp){
 WORD cond = strlen(str) ^ strlen(strp);
 WORD de = 0;
 while(de <strlen(str)){
 cond = cond + ((BYTE) * (str+de)) ^ ((BYTE) * (strp+de));
 de = de +1;
 }
 return cond;
}
BYTE memset(WORD dest,WORD c, WORD ammt){
 WORD de = dest;
 while(de<(dest+ammt)){
 (BYTE) *(de) = c;
 de = de +1;
 }
}
BYTE memcpy(WORD src,WORD dest, WORD ammt){
 WORD de = 0;
 while(de<ammt){
 (BYTE) *(de+dest) = (BYTE) *(de+src);
 de = de +1;
 }
}
BYTE strcpy(WORD dest,WORD src){
 WORD de = 0;
 while((BYTE) *(de+src) != 0 ){
 (BYTE) *(de+dest) = (BYTE) *(de+src);
 de = de +1;
 }
 
}
BYTE str_arr_ind(WORD str_ptr,WORD index){
	WORD de = 0;
	WORD int_ind = 0;
	while(int_ind != index){
		while((BYTE)*(str_ptr+de) != 0){
			de = de+1;
		}
		while((BYTE)*(str_ptr+de) == 0){
			de = de+1;
		}
		int_ind= int_ind+1;
	}
	return de+str_ptr;
}
BYTE strlen(WORD src){
 WORD len = 0;
 while((BYTE) *(len+src) != 0 ){
 len = len +1;
 }
 return len;
}
BYTE pow(WORD base, WORD exp){
	WORD de = 1;
	WORD result = base;
	
	while(de<exp){
		result = result *base;
		de = de +1;
	}
	return result;
}
BYTE stoi(WORD str_ptr){
 WORD string_length = strlen(str_ptr);
 WORD de =0;
 WORD final_num = 0;
 while(de < string_length){
 final_num = final_num + (((BYTE)*(str_ptr+de)) ^48) * pow(10,(string_length -de));
 de = de+1;
 }
return final_num/10;
}
BYTE atoi(WORD num){
 WORD buffer = "18446744073709551616";
 WORD dnum = num;
 WORD i=1;
 WORD buf_len = strlen(buffer);
 while(i < buf_len){
 (BYTE) *(buffer + buf_len - i) = dnum % 10;
 (BYTE) *(buffer + buf_len - i) = 48 ^ (BYTE)*(buffer + buf_len - i);
 dnum = dnum / 10;
 i = i + 1;
 }
 (BYTE) *(buffer + buf_len - i) = dnum % 10;
 (BYTE) *(buffer + buf_len - i) = 48 ^ (BYTE)*(buffer + buf_len - i);
 dnum = dnum / 10;
 i = i + 1;
return buffer;
}
BYTE clrscr(){
 memset(0,32,1024);
}
BYTE malloc(WORD tsize){
 WORD i =0;
 WORD k =0;
 WORD heap_loc = 0x01FFFFF;
 while((BYTE) *(heap_loc+i) == 1){
 
 if((BYTE) *(heap_loc+i) == 0){
 (BYTE)*(k) = 90;
 k=k+1;
 if( 0 == (WORD) *(heap_loc+i+1)){
 asm_d("JMP #break_malloc");
 }
 if( tsize < (WORD) *(heap_loc+i+1)){
 asm_d("JMP #break_malloc");
 }
 }
		i = ((WORD) *(heap_loc+i+1)) + i;
 }
 asm_d("LABEL break_malloc");
 (BYTE) *(heap_loc+i) = 1;
 (WORD) *(heap_loc+i+1) = tsize+5;
 return heap_loc+i+5;
}
BYTE realloc(WORD ptr,WORD tsize){
 WORD new_blk = malloc(tsize);
 WORD mov_ammt = ((WORD) *(ptr-4))-5;
		 memcpy(ptr,new_blk,mov_ammt);
		 free(ptr);
return new_blk;
}
BYTE mallocv(WORD siz_t){ //dynamically allocate a vector
 WORD blk_ptr = malloc(siz_t+4);
 (WORD) *(blk_ptr) = siz_t;
 return blk_ptr+4;
}
BYTE reallocv(WORD ptr_blk,WORD siz_t){
 WORD blk_ptr = realloc(ptr_blk-4,((WORD)*(ptr_blk-4))+siz_t+4);
 (WORD) *(blk_ptr) = ((WORD)*(ptr_blk))+siz_t;
return blk_ptr+4;
}
BYTE free(WORD ptr){
	if((BYTE) *(ptr+(WORD)*(ptr-4)) == 0){
		
		(BYTE) *(ptr-4) = ((BYTE) *(ptr-4)) + (WORD) *(ptr+(WORD)*(ptr-4)+1);
	}
 (BYTE) *(ptr-5) = 0;
}
==Operating system==
Tenshi C has been used to develop a small operating system. 
It's more like a monolithic program that runs with no memory protection. It is still in production and may be found in the implementation.
Shell commands
 
 stab [memory location] [integer byte] - similar to the poke command in old basic
 stabf [memory location start] [memory location end] [integer byte] - fills the location from that range
 help - You don't get any help
 clear - clear screen
 test - prints the letter A accross the screen
 
All memory locations used in commands must be written in decimal.
Memory map of the operating system
0x0000000 - 0x0000400 MMIO screen
0x0001000 - 0x0002000 MMIO IO Keyboard
0x0005000 - Start of program memory
0x01FFFFF - Start of Heap - Grows up
0x0FFFFFF -Start of stack
0x1000000 - Interrupt vector table
0x2000000 - Text Area
0x3000000 - Start of filesystem - Grows Up
==External resources==
*Implementation
Category:Languages Category:Turing complete Category:Implemented Category:Low-level Category:2023