C compiler

Hi guys (and gals). I've decided to make a C interpreter in Snap!. Because it would be cool.
https://snap.berkeley.edu/snap/snap.html#present:Username=pumpkinhead&ProjectName=C%20dev%20release
This isn't the version I'm working on. It's just a copy of the latest version of my C interpreter that, as far as I know, actually works, since I'm always going to add more features when working on this.

Well as the title says I am still working on this -- most features in C are not supported yet. It took me about 4 days to reach to this point (I have summer vacation and not really anything to do). But here is a list of what is supported at the moment of writing this:

  • Main function (obviously)
  • Expressions
  • Arithmetic (+, -, /, *), bitwise (&, |, ~, ^), and ternary (?:slight_smile: operators. (Dumb auto-emoji thing I hate those...)
  • Only int and char types
  • Type conversions (only explicit)
  • User-defined functions with arguments/parameters
  • Control statements (if, while, for, do)
  • #include preprocessor directive

Due to the current lack of pointers, there are no strings. So printf can't be used. Instead, you can use the putchar function, which puts a character (as an int) on screen. Keep in mind that what you write only shows up once you put a newline character. ('\n', code point 10)

There are also built-in header files, which are used to declare functions that connect with Snap!. Built-in header files include <stdio.h>, <turtle.h>, and <sensing.h>.

<stdio.h>

This just declares the putchar function.
int putchar(int character)

<turtle.h>

This allows the use of pen (a.k.a. turtle graphics) to draw stuff.

int turtle_create(void) creates a new turtle and returns its ID number. its ID will be used for every turtle function as the first parameter to identify which turtle to use

void turtle_remove(int id) deletes a turtle with the given id. if any function is called with an invalid id, the function does nothing.

the rest of the functions are wrappers for pen/motion blocks:
void turtle_pendown(int id)
void turtle_penup(int id)
void turtle_penhsv(int id, int h, int s, int v)
void turtle_pensize(int id, int size)
void turtle_goto(int id, int x, int y)
void turtle_turn(int id, int degrees) turns clockwise if positive, counter clockwise if negative
void turtle_move(int id, int steps)

<sensing.h>

These declare functions that allow interaction with the user's mouse and keyboard.

int mousex(void)
int mousey(void)
int mousedown(void) returns 1 if mouse is down, else returns 0
int keydown(char key) returns 1 if the key specified is pressed. e.g. 'a', '7'. however does not support space (because i'm lazy just use a different key) and arrow keys, because arrow keys in the sensing block need more than one character.

It isn't a very fast interpreter (cough because it's written in snap). But a plan I have is to make a separate project that, instead of interpreting the generated "abstract syntax tree" of the program directly, would compile it into JavaScript, then run the generated JavaScript code. The parser and the compiler would still be run on Snap! code. The reason I'm not doing that in the first place is because I'm pretty sure the devs are discouraging the use of JavaScript. So the user has to manually turn on JavaScript. Also there's no way to detect if JavaScript is enabled. (I guess since it throws an error if you try to run JS with it disabled, I could check if an error is thrown when JS is run. Except you need JS on to use the "Catch errors library"... Or maybe I could do something else... since code execution stops if there's an error...)

If you want to use this program but don't know basic C programming, then... uh... I don't know. Search it up online I guess. But the good thing is, the feature set of the current state of my C compiler is so small it's basically just strictly typed JavaScript. So if you know at least basic JavaScript (which I'm sure most regulars on this forum do), then lucky you! All you need to know is how types work in C.

This (and the other libraries except for getters/setters) is fixed in 7.0. Stay tuned, or you can run the dev version.

Sounds like a fun project. Especially when you get to pointers. :~) Are you just going to have a huge array called "memory"? Or get pointers into the browser window's memory?

I did that here: Snap! Dev tools

Yeah, that is exactly what I did -- I already made that in the project in anticipation for pointers.

Uh... That's not possible since JavaScript doesn't have pointers, so variable memory addresses are unobtainable. However, objects are passed by reference, which could be used to emulate pointers. But in C you are able to add integers to pointers to get another pointer relative to the original pointer. I don't think there's a way to emulate this if you are using references in JavaScript.

He could do the same thing in JS that he plans to do in Snap!, namely, make a huge array and use indices into the array as simulated pointers. But he couldn't get real JS pointers in Snap! either.

It's been a while but I finally started working on this again. I decided to work on the compiler, and I got rid of the interpreter stuff because it's really slow and I don't want to have to handle both the compiler and the interpreter.

I also chose to make it compile to WebAssembly instead of asm.js. I just originally planned to use asm.js because I thought that I couldn't execute dynamically created wasm code. Turns out I can. And asm.js is discontinued anyway.

The feature set has changed a bit because I had to write the compiler. I would say "from scratch" but I still have the parser and stuff. So technically not from scratch.

  • Main function
  • Expression
  • Artihmetic operators, bitwise operators (except ~ because there isn't a direct instruction for that in wasm for some reason). Ternary operators are missing. I forgot about that.
  • int, char, long types
  • I got strings now. It's so cool.
  • If and while control statements. There's no for for now because one specific detail about its functionality scares me. And there's no do also because I forgot. I kinda just got excited to share this when I finally got hello world working.
  • #include preprocessor directive

I added void printf(char* string) in stdio.h -- it just prints a string literal. I also added long time(void) in sensing.h which is supposed to report the time in milliseconds, but for some reason it throws an error when it's called. It just says some number can't be converted to a BigInt. I have no idea what it's talking about. I also added support for the space key in keydown.

Here is the link to a copy of the project:
https://snap.berkeley.edu/snap/snap.html#present:Username=pumpkinhead&ProjectName=C%20dev%20release
I put some code examples in the Stage.

Isn't this so cool.

Could not fetch project C
This project does not exist

Woops, wrong link
I fixed it now

Ok. I like it.

Thanks for making me smile.

I bet you can do bitwise not with some arithmetic expression, maybe -1 - x or some such thing? I'm too tired to work it out right now.

I searched online and xor by -1 would work. But I think there is an artihmetic expression to do NOT -- I think it'd be -x - 1

That's the same as what I said! :slight_smile:

I messed up when mentally rearranging the equations to see if they were the same.