Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hello world program #52

Open
1 of 3 tasks
jdpage opened this issue Aug 10, 2018 · 2 comments
Open
1 of 3 tasks

Hello world program #52

jdpage opened this issue Aug 10, 2018 · 2 comments

Comments

@jdpage
Copy link
Collaborator

jdpage commented Aug 10, 2018

  • Decide on the goal program
  • Create issues and project cards for the required steps
  • Compile and run the program

Just to make the goal clear for the "Hello world!" milestone, here's the test program:

use kernal

fun print(text: &[u8])
  for c: u8 in text do
    kernal.chrout(c)
  end
endfun

fun main()
  print("hello, world!\n")
endfun

Original commentary:

So, what's interesting here? Well, we have some basic control flow, a function call, all good. We have a slice. Additionally, we have a KERNAL call. KERNAL calls have "weird" (in jeff65 terms) calling conventions, so this could (provisionally) be done in a few ways:

  1. kernal.chrout is a real, honest-to-god linker symbol with type fun(u8), value 0xffd2, and an associated calling convention.
  2. kernal.chrout is a compiler intrinsic which emits the appropriate assembly directly.
  3. kernal.chrout is a real function implemented in assembly which puts its argument in the A register and then does jsr $ffd2.

Each of this is interesting in a different way. Doing 1 right out of the gate means that we ensure that our code generation for function calls isn't hard-coded to a particular convention, but means we have to support two of them. Doing 2 might just be a bad idea--my gut feeling is that that's not really what compiler intrinsics are for. Doing 3 means that we implement the ability to (a) load the symbol table from referenced units and use it, and (b) link multiple units together. (I think technically we can already do that last thing, but there's no support for it in the command-line driver.)

Obviously 1 is the "correct" way to do it long-term, but 3 is good enough for now I think.

For bonus points, implement an "improvement" pass (NFCE terminology) which notices that the range variable c is only used as a function argument, and loads it directly into the argument slot for the kernal.chrout function.

@jdpage jdpage added this to the Hello world! milestone Aug 10, 2018
@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

An alternative program would be:

use console
fun main()
  console.print("hello, world!\n")
endfun

Where console.print is implemented directly in assembly. This means that we don't implement any control flow, though.

@jdpage
Copy link
Collaborator Author

jdpage commented Aug 10, 2018

Woody, I've assigned this to you to review. Once we've decided on the actual goal, you can either assign it back to me to create the issues, or do it yourself, and then either hang onto the issue or un-assign it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants