Tenshi C
- This article is not detailed enough and needs to be expanded. Please help us by adding some more information.
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