tekknolagi/stackx

[WIP] Syntax proposal for CompilerV0

Opened this issue ยท 31 comments

It's largely based on Rust but simplified.

Variable declaration

let a : int = 1;
  • Done?

or for constants:

const b : string = "hello";
  • Done?

Reassignment

let a : int = 2;
a = "hello"; // wrong! type mismatch
a = 5; // sounds good

const b : bool = true;
b = false; // wrong! b is constant
  • Done?

Simple math

let a : bool = 1 + 2 == 3;
  • Done?

If-statements

if (condition) {
  // code...
}
  • Done?

or, with another branch:

if (condition) {
  // code...
} else if (another_condition) {
  // code...
} else {
  // code...
}
  • Done?

Switch cases

let num : int = 25;

// can also be written switch num { ...
switch (num) {
  case 25 {
    // do stuff
  }

  case 30, 40 {
    // do stuff if num is 30 or 40
  }

  case (25, 30, 35) {
    // can also use parens
  }

  default {

  }
}
  • Done?

Loops

While

while (true) {
  // do a thing
}
  • Done?

For

for (let x : int = 0; x < 10; x += 1) {
 // do a thing
}
  • Done?

Functions

func add_two_numbers (a : int, b : int) : int {
  return a + b;
}
  • Done?

Structs

struct Slice {
  buffer : byte*,
  size : int
};
  • Done?

Tell me what our default language is so that we can minimize such issues :)

@akkartik default language? Do you mean the sort of basis parent language whose syntax we are simplifying?

Yes, it shall be Rust. :)

I've decided to revert to C-style while and for loops because we do not have iterators or anything fancy that Rust-style "requires".

Still not hooked on having := as our assignment operator :/

How do you feel about set a = 5;?

Or we could go the route of normal a = 5.

Thoughts on let/const vs let/let mut?

if (set a = read()) { ... } ??

@KCreate are you suggesting that it should be required in loops to use the word set?

No, I think requiring set at all is a bad idea

I'd say we'll go for the normal way (a = 5).

Regarding let/const vs let/let mut, I'd prefer let/const.
let mut makes mut look like some kind of attribute.

Does Rust have :=?

Well then, let's follow Rust :)

I notice your conditional and loop examples above use parens:

if (condition) {
  // code...
} else if (another_condition) {
  // code...
} else {
  // code...
}

Let's just follow Rust exactly:

if condition {
  // code...
} else if another_condition {
  // code...
} else {
  // code...
}

@akkartik Charly has this too :)

Just added syntax for a switch statement

How easy do we want this first compiler to be? I don't know how we're weighing that against number of features / ease of implementing another language in this compiled one, but I think that should be discussed at some level of technical detail.

I'd go for C level simplicity, maybe even less.

I've added syntax highlighting using the swift tag.

Also some other points:

  • Do we want typedefs or should everything be in one namespace?
  • Do we want a certain level of oop? (Even if it's just syntax sugar)

I'd say no to the second one but don't know enough / can't think enough at the moment to offer an opinion on namespacing.

What should be the syntax to create pointer types?

I'd suggest type*

Only if we make it left-associative. I have severe issues with people who write C-style pointers like that:

int* a, b; // misleading! only a is a pointer

What about making it right-associative?

*int that is.

Are there languages who have a different pointer syntax?

Then it's kind of annoying for dereferencing. I think keeping it C/Rust like in form makes sense, but changing the associativity would be a strong preference.

Why would that interfere with dereferencing?

BTW, what's rust's pointer syntax?

Since traditionally dereferencing has used that exact syntax. Rust is (very nearly) the same as C.

Our syntax is context free so I don't think we'll have to worry about that.

How about switching the meaning of * and &?

let foo : *int; // pointer to int
*test; // pointer to variable test
&test; // dereference test

Hard veto on that. Very confusing. We don't have to worry about it at a technical level, sure, but as someone who TAs students quite regularly... they already get confused with the dual meaning of * in C/C++. This would not help.

I see. I however don't see a problem with using the *int syntax.

We know exactly in our syntax when the type grammar has to kick in, so it can't be confused with the dereference operator.

let a : *int = ...;
        ^
        |
        +- The parser knows it has to parse this expression as a type.

tmp = 5 *int;
        ^
        |
        +- This is "5 times int", where int would be a semantic error as it's a reserved name.

Yeah that's fine, I think; I merged that intro master.