Tenshi C

From Esolang
Jump to navigation Jump to search
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

External resources