• Ubiquitous libc

    agp.cooper03/17/2019 at 02:20 2 comments

    Libc Functions

    As I parse the "self compiling" compiler I see just how ubiquitous "libc" is.

    But I think I the "atomic" functions are:

    1. fgetc()
    2. fputc()
    3. feof()
    4. malloc()
    5. free()

    Actually I only need a memory pointer to the "heap" for malloc() and free().

    "feof()" makes the list as I need to know when input (serial) data is available.

    I have actually coded in ActsL most of the functions I need:

    • itoa() (no division used)
    • getchar()
    • putchar
    • puts()
    • gets()
    • fputs()
    • fgets()
    • strcat()
    • strcmp()
    • strchr()
    • strcpy()
    • strlen()
    • and others

    Still more to code.

    The ubiquitous fprintf()

    "fprintf()" is a complex and large procedure for a simple compiler.

    As the arguments are variable, the count needs to be given to the function in some manner. Perhaps a global variable for the argument count or a NULL delimiter on the stack.

    Better to use fputs() and construct a string using strcpy(), strcat() and itoa().

    Looking Forward

    I was contemplating my TTA8 as a target (when I get it working!).

    The memory page size is limited to 64 bytes but I have up to 255 pages. So it is doable.

    I now have the "p code" (i.e CodeGen.h) specification for the CPU interpreter the emulate.


  • Acts Language Elements

    agp.cooper03/15/2019 at 08:31 0 comments

    The Acts Language Elements

    Tarvo's original language specifications was:

    • + - * / %
    • & | ^ << >>
    • == != < <= > >=
    • deref <variable>
    • =
    • quoted string literals (i.e. "...")
    • C style comments (i.e. /* ... */ and // ... \n)
    • int <variable>
    • ref <variable>
    • <expression> arg <expression> arg ... call <functionname>
    • fun <functionname>  <statements> endfun
    • <expression> return
    • if <expression> then <statements> endif
    • while <expression> do <statements> endwhile
    • continue
    • break

    So pretty complete, actually his "actsl.a" program self compiles.

    Hello World!

    Here is the "Hello World!" program in ActsL:

    int rtn
    int nul
    int buff
    fun init
      ref rtn ref nul =             // Make null point to nulv (i.e. nul=&nulv) 
      32 arg call malloc ref buff = // Create a buffer (buff) for your string 
      0 return
    fun PutStr
      buff arg call puts nul =      // Print the buffer (buff)
      0 return
    fun main
      call init nul =               // Initialise variables
      /* Copy "Hello World!" into a buffer (buff) */
      "Hello World!" arg buff arg call strcpy nul =
       call PutStr nul =            // Call print string
      0 return                      // Return okay

    Okay, its a bit more complicated than it has to be but it show the language elements.

    Another Code Example

    An example of "his" code (although I have played a bit with it!), first in C:

    void error (char *text)
            printf ("%s:%d: %s\n", infile, line, text);
            exit (1);

    Now in ActsL:

    fun error
            buff arg line arg infile arg "%s:%d: %s\n" arg call printf nul =
            1 arg call exit nul =

    In his ActsL code he has use "buff" instead of "text" (not important), but he fails to use a return statement (a bit lazy and it cost me time to work this out!), and "nul" has been assigned the address of "nulv" during the initialisation (otherwise he should have used "ref nul =" and not "nul =").

    Note, if your not careful with assignment (i.e. "="), it is very easy to generate a segment fault and no idea where the code error is!

    Finally you will see he uses "printf()" and "exit()" from "libc". So even though his code self compiles, you need to be aware that it still uses libc.

    Missing Language Elements

    Although he can set arguments (i.e. "arg") for a call, an ActsL function (i.e. "fun"/"endfun") can not read then. Therefore I add:

    • <expression> param

    Here is an example of its use:

    fun test1
      1 param return
      98 arg 99 arg call test1 nul =
      rtn arg "\nReturn %d\n" arg call printf nul =

     "fun test1" was called with two arguments (98 and 99), the first parameter (=99) was returned.

    Next, I added "else" to the set of commands.

    Next, I added "// .. '\n'" comments to the set of commands (I like having both).

    Finally, I tokenised "halt" when the EOF is found.

    And I nearly forgot, added support for "_" in names and negative integers.

    Final Notes

    All variables are global. This is a bit of a pain, so I use lower case for code and will use upper case for library code.

    And if you have not worked out, delimiters are white spaces (i.e. " \t\n").

    As I intend to port the code to one of my home brew CPUs, I will not have the luxury of access to libc. I have made a start on this.