# My next comp/c design

I'm thinking about rewriting comp/c, *again*. This would be my Fourth rewrite,
a number that sounds about right.

The idea behind the design would be that the compiler would only be a set of
words allowing a C program to be interpreted "as Forth", provided that the
tokenization is correct. Let's use an example:

  int foo(int a, int b) {
    int x = a+3*b;
	return x;
  }

That could be see as the exact equivalent of (the "})" word doesn't exist yet
and would take a moustache and yield its associated HAL operand):

  create{P} a
  create{P+4} b
  create{F} x
  code foo ( b a -- n )
    dup, \ wiggle room for W
    b }) @,
    3 i) *,
    a }) +,
    r!
    x }) @,
    8 ps+, [rcnt] neg rs+, \ clean up PS and RS
    exit,

Now, how do we get from the C code to the Forth code? That's the question.

Well, there's another question, the one of "correctness checks", which also
needs to be consider if we don't want the new comp/c design to be functionally
lesser than the previous one, but for now we only consider code generation.
Checks are considered later in this text.

So, how do we do it? First, there's tokenization. That's an easy one. There's
already a token system in comp/tok, but I'm thinking about something even
simpler: tokexec< ( w tok -- )

It would execute "w" in a context where "word" is replaced by "tok". This
changes the C code to:

  int foo ( int a , int b ) {
    int x = a + 3 * b ;
	return x ;
  }

Now let's interpret this. How do we define our words? First, we'll need multiple
namespaces. "int" in the global context doesn't mean the same thing as "int" in
the function signature and "int" in the function body. So we'll have something
like:

  ns[ global
    : int ... ;
  ]ns
  ns[ funcsig
    : int ... ;
  ]ns
  ns[ funcbody
    : int ... ;
  ]ns

On top of that would be the "symbols" namespace where "create" calls add their
resulting words.

The global "int" is equivalent to "code", which consumes the next token and thus
make "int foo" equivalent to "code foo".

Now, "int foo" could also mean the prelude for "int foo;", or "int foo[42];",
but for now, we ignore this so that we can keep our ideas straight, but this
must certainly be considered before jumping head-first into an implementation.

Next comes the "(", which would have the effect of activating the "funcsig"
unit.

The next "int", from the "funcsig" unit, is the equivalent to "create{P++}",
which consumes the following token as the moustache name.

The following "," is a noop in terms of code generation.

The following "int" does the same thing as the previous one.

")" collects the argument size (8) with something equivalent to "0 @{&++} const
SZ". We're still in "funcsig" context.

"{" puts us in "funcbody" context.

In "funcbody" context, "int" declares a local variable. The big problem to
sidestep here is the possibility that an expression follows the declaration.

In the current generation of comp/c, we sidestep this by keeping the sexpr in
a string to be evaluated later. With the new comp/c design, this would be a
problem.

What we can do is to simply allocate RS space in multiple steps. It's slightly
slower, but buys us a lot of simplicity. So here we go.

So, "int" would be the equivalent of "create{F++}", with the addition of
incrementing a counter "RS space to allot when we encounter an expression". That
counter would now have the value of 4. Then, we place ourselves in "funcdecl"
context.

The "funcdecl" context only has "=" and ";". "=" allocates current RS counter,
places the HAL operand of the latest declared variable on compile time PS, then
behaves like a regular "=" from the "funcbody" context.

Assignment operators from the "funcbody context" expect a ( halop ) PS and then
do the following:

1. Place ourselves in "expr" context.
2. Push "99" on PS (a high priority)
3. Push a reference to "!," on PS.
4. Interpret the two following words.
5. We're back in "funcbody" context.

## Expressions

Alright, I tried real hard to think about the idea of "straight-interpreting"
infix expressions. It's possible, for sure, it's kind of what my previous DuskCC
versions did. But it ends up being really complicated, code wise. I don't want
to go back to this. So, the comp/c/term and comp/c/sexpr systems are good, I
want to keep them.

So what would happen is that calling an identifier in "funcbody" context would
trigger the "sexpr" system, which would consume incoming tokens until ";" is
met.

TODO: continue this line of thinking. I was inspired one morning to think about
it, hence this document, but now I'm not. There's something to this design idea,
but it needs work. Later.
