Gip-Gip Posted April 4, 2016 Share Posted April 4, 2016 (edited) I have given the compiler the name AtaC(Atari C, Pronounced Attack). Any other suggestions? I'm making a new Atari 2600 compiler for a custom C-like language(in C89). It is being created to be efficient but also to hide multi-frame calculations from the programmer(it will notify the programmer, however, if multi-frame calculation is needed), as well as be more readable than assembler. I am currently developing the assembler, and development on AtaC has been paused until it is finished. Here's the GitHub page if you want to watch me develop that mess All examples and syntax specifications have been removed(on accident, to an extent). I will come up with those tomorrow. Edited July 22, 2016 by Gip-Gip 4 Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 4, 2016 Share Posted April 4, 2016 How are you planning on handling timed code in the display kernels? Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 4, 2016 Author Share Posted April 4, 2016 How are you planning on handling timed code in the display kernels? While all of it will be handled inside of the init function, I will more than likely add an asm statement like in GCC. while it would require making a built-in assembler, I don't want the main feature of the programming language(smart code placement) to be soiled by slow code generation. This should not be needed with basic graphics, as a few equal statements should not consume that many resources. The amount of scanlines vblank and overscan consume will be up for control from the command line. Any other timing related things such as NOP and STA WSYNC will be provided as functions(nop and next_line) 1 Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 4, 2016 Share Posted April 4, 2016 Including an assembler would be a good idea. Will this support two line kernels? What about kernels that are exact multiples of 76 cycles and don't use wsync? I like what you're trying to do. It would be great to have a higher level language for game logic, but still have flexible kernel options. 1 Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 5, 2016 Author Share Posted April 5, 2016 Will this support two line kernels? It can technically be two lines, since it is going to be a whitespace-insensitive compiler What about kernels that are exact multiples of 76 cycles and don't use wsync? if you're willing to pad, yes, it will be possible 1 Quote Link to comment Share on other sites More sharing options...
Kylearan Posted April 6, 2016 Share Posted April 6, 2016 You may want to take a look at K65, a very powerful compiler and linker framework for the VCS: http://devkk.net/wiki/index.php?title=K65 It's not really C, but similar to it. It abstracts a lot of things (functions, loops, inlining, bank switching etc.), optimizes the placing of code and data segments for you during linking (aligned/unaligned) and has VCS-specific keywords like wsync, but still gives the programmer full control over everything if needed. Once you get used to its syntax and idiosyncrasies, it speeds up development considerably; especially the linker is a great improvement over having to do it manually like with dasm. KK, the developer, is also quite open to feature requests 2 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted April 6, 2016 Share Posted April 6, 2016 AtaC sounds awesome Gip-Gip, very cool to see another high level language initiative for the VCS! Looking forward to following this project, particularly the aspects of kernel accessibility for the high level code. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 6, 2016 Author Share Posted April 6, 2016 You may want to take a look at K65, a very powerful compiler and linker framework for the VCS: http://devkk.net/wiki/index.php?title=K65 It's not really C, but similar to it. It abstracts a lot of things (functions, loops, inlining, bank switching etc.), optimizes the placing of code and data segments for you during linking (aligned/unaligned) and has VCS-specific keywords like wsync, but still gives the programmer full control over everything if needed. Once you get used to its syntax and idiosyncrasies, it speeds up development considerably; especially the linker is a great improvement over having to do it manually like with dasm. KK, the developer, is also quite open to feature requests K65 looks like a great compiler, but I do have things I want to do differently than it, such as: an Open-Source compiler under the ISC license(if the source is legally out there, I can't find it) "cleaner" variable declaration(instead of doing var foo = 0x80, ram: foo = value) "cleaner" data declaration(instead of doing data foo{data}, rom: foo[] = {data} or rom: foo = value) variable declaration inside functions, similar to C99 all non-whitespace non-operator characters counting as valid variable names true whitespace-insensitiveness hidden bankswitching(for calc, all the other call will be the first segment) a few more things I forgot when I made this post I am now going to go make a standard over at GitHub, so my code doesn't change so much anymore Quote Link to comment Share on other sites More sharing options...
Kylearan Posted April 7, 2016 Share Posted April 7, 2016 K65 sure has some questionable design, I have been annoyed by it more than once. But its greatest strength is providing a good layer of abstraction while at the same time leaving the developer in full control of everything if need be, which IMHO is key for the VCS with ist limited resources (RAM, ROM) and need for precise timing (cycles). Keep that in mind when developing your compiler, especially when it comes to "hidden bankswitching", "variable declaration inside functions" etc., which (without knowing exactly what you mean by that) look like dangerous candidates to be done wrong. I'll follow your project with interest in any case! Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 7, 2016 Author Share Posted April 7, 2016 (edited) Keep that in mind when developing your compiler, especially when it comes to "hidden bankswitching", "variable declaration inside functions" etc., which (without knowing exactly what you mean by that) look like dangerous candidates to be done wrong. What I meant by "hidden bankswitching" is that if a function goes over a bank, it will either automatically bank switch in the function or the function will be moved into the other bank, depending on how much room the function takes up in the bank As for "variable declaration inside functions", it was an idea I had that came from experience with C, where variables could be declared in functions(which I somewhat put inside the syntax standard, but it's only allowed in init). The cleaner variable declaration is simply to make variable declaration more automatic and less manual, but there will also be alias object handlers(some weird word I chose for the part of a logical line that "handles" what's done with it) and a RAM array, for those who really want it(and there will also be some way to work with addresses). Edited April 7, 2016 by Gip-Gip Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 7, 2016 Author Share Posted April 7, 2016 If anyone sees any issue with my syntax outline, please say so! I will be starting compiler dev exactly 24 hours from the creation of this post, unless a major revision is needed! To look at my syntax outline, click here Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 7, 2016 Share Posted April 7, 2016 Personally I find the design of this language a bit awkward. Some if seems like it tries to be different just to be different. I also have serious concerns about how well it lends itself to making an actual Atari game. The draw function in particular raises the most concern. I just don't think the VCS has enough resources to right anything but the most basic kernels using your proposed language. Have you thought about trying to make a framework first before tackling something as complex as a compiler? You could take an existing c++ compiler and couple it with some hand written assembly routines to produce something similar to what you are proposing here without having to reinvent the wheel. Here is some feedback on the current syntax outline: Addresses may need to deal with ZeroPage vs Absolute. You may want to assign the high/low byte of an absolute address to a variable. Logical Lines example says value 0 in description but uses 1. Is there no single line comment? // Functional separators lack clarity on bank and inline status. draw is problematic because you can't easily switch kernels or handle multiline kernels draw should probably have a scanline count parameter too for performance reasons asm: shouldn't require ;, instead a new line should terminate the statement "ROM variables are constant" - so call them contants Multiply(+=) should be *= support for fixed point, signed/unsigned, and 16bit integers seems to be missing? Shouldn't keep if equal be if: foo != bar[1] { foo = 0 } instead of foo = foo == bar[1]; I find it odd that the RAM variables are declared init. They have global scope, so I would expect to declare them outside of a function separator. The concept of pointers/references seems to be omitted. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 8, 2016 Author Share Posted April 8, 2016 (edited) ZackAttack, on 07 Apr 2016 - 5:22 PM, said: Logical Lines example says value 0 in description but uses 1. Multiply(+=) should be *=Those where typos, thanks for pointing those out ZackAttack, on 07 Apr 2016 - 5:22 PM, said: Personally I find the design of this language a bit awkward. Some if seems like it tries to be different just to be different.It may seem that way, but it's actually just so the compiler classifies as truly whitespace-insensitive. For example, I can't make a variable in C without putting a space between the type identifier(it's int in the example int number = 0) and the variable name(at least in GCC). To go around this, I just made it mandatory to put a colon between the handler and the variable(and then the handler became a large part of code). ZackAttack, on 07 Apr 2016 - 5:22 PM, said: Is there no single line comment? //Now there is ZackAttack, on 07 Apr 2016 - 5:22 PM, said: Shouldn't keep if equal be if: foo != bar[1] { foo = 0 } instead of foo = foo == bar[1];Good point. It is fixed. ZackAttack, on 07 Apr 2016 - 5:22 PM, said: I find it odd that the RAM variables are declared init. They have global scope, so I would expect to declare them outside of a function separator.RAM variables are declared in init as that initializes them to zero(or any other number provided), as well as shields them from looping. I have included the syntax specification to allow RAM variables outside of init, but they will not be initialized(whatever value is at that address is what it is). ZackAttack, on 07 Apr 2016 - 5:22 PM, said: The concept of pointers/references seems to be omitted.I expanded the definition of addresses to include variable representation(crappy pointers that can only access zero-page memory), and added the reference operator ZackAttack, on 07 Apr 2016 - 5:22 PM, said: "ROM variables are constant" - so call them contants asm: shouldn't require ;, instead a new line should terminate the statementIt's a consistency thing.. the semicolon thing will be optional(some people, including myself, like the feature) but the reason rom variables are called such is because that's the part of memory they're part of. It would seem out of place(to me) for a C type identifier in a source file. They will be interchangeable. ZackAttack, on 07 Apr 2016 - 5:22 PM, said:Addresses may need to deal with ZeroPage vs Absolute.This is automatically handled by the compiler(depending on the value of the address) ZackAttack, on 07 Apr 2016 - 5:22 PM, said:support for fixed point, signed/unsigned, and 16bit integers seems to be missing?Done(ish), done(ish), and done ZackAttack, on 07 Apr 2016 - 5:22 PM, said:You may want to assign the high/low byte of an absolute address to a variable.It is now possible. ZackAttack, on 07 Apr 2016 - 5:22 PM, said:draw is problematic because you can't easily switch kernels or handle multiline kernels draw should probably have a scanline count parameter too for performance reasonsYou're right. My solution? Multiple Draw Functions of course(with their accompanying draw variable perimeters) (what you meant by multi-line kernels is false, remember, wsync(and padding) is always an option. the language is not that high-level. draw loops do not have an wsync placed at the end anyways, so was it the wording?) ZackAttack, on 07 Apr 2016 - 5:22 PM, said:Functional separators lack clarity on bank and inline status.you can specify the bank a function is in with the bankX: handler, and I think object: handlers are sufficient as inline functions(tell me otherwise, if you think so)I'm surprised my standard is even readable! Thanks for the feedback! Edited April 8, 2016 by Gip-Gip Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 8, 2016 Share Posted April 8, 2016 What is the reason for "whitespace-insensitive" being a major design goal? Regarding the multiple draw functions. Imagine you are building a small game that has a title screen. When you press the button it starts the game which has a status bar at the top and the level on the rest of the screen. So you have 3 kernels. The first kernel for the title screen will apply to all 192 scanlines. The second kernel will apply to the top 32, and the third will apply to the bottom 160. I think your spec still fails to address this common situation where depending on the state of the game you will need to display different kernels. Quote Link to comment Share on other sites More sharing options...
danwinslow Posted April 8, 2016 Share Posted April 8, 2016 Yeah, I have to wonder too. Whitespace insensitivity is almost exactly the very last thing I would care about. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 8, 2016 Author Share Posted April 8, 2016 Regarding the multiple draw functions. Imagine you are building a small game that has a title screen. When you press the button it starts the game which has a status bar at the top and the level on the rest of the screen. So you have 3 kernels. The first kernel for the title screen will apply to all 192 scanlines. The second kernel will apply to the top 32, and the third will apply to the bottom 160. I think your spec still fails to address this common situation where depending on the state of the game you will need to display different kernels. Thanks for bringing that up! I replaced that with layouts(essentially inline linker scripts). What is the reason for "whitespace-insensitive" being a major design goal? It's for compiler simplicity and a personal preference(I did remove the colon requirement for handlers though) Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 8, 2016 Share Posted April 8, 2016 It's for compiler simplicity and a personal preference(I did remove the colon requirement for handlers though) I don't get how it simplifies the compiler though. Either way the lexical specification will need a token class for white space. The parser will have slightly different semantics, but it doesn't seem like it would be significant. Your rainbow example is laid out nicely and easily readable thanks to white space. It doesn't seem like no white space is really your personal preference. Also, can you add some more complete examples that demonstrate the layout construct? I'm having trouble visualizing how it would be used for the three kernel example I gave before. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 8, 2016 Author Share Posted April 8, 2016 I don't get how it simplifies the compiler though. Either way the lexical specification will need a token class for white space. The parser will have slightly different semantics, but it doesn't seem like it would be significant. Your rainbow example is laid out nicely and easily readable thanks to white space. It doesn't seem like no white space is really your personal preference. Before you pointed that out, I was thinking of loading the line into a buffer and parsing the text. Now, I realize that I could just convert everything into symbols as things are read in. Wow, I was overthinking this. As far as personal preference goes, sometimes I like to make code into blobs of text or ASCII art(it's a thing I do when I'm really bored), which isn't really practical at all(and more than likely will never be done with this language). Either way, thank you for pointing everything out and criticizing me(your making me think)! 1 Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted April 8, 2016 Share Posted April 8, 2016 Converting source code into ascii art is a great idea! There are a lot of good resources about compiler design theory and implementation. You may want to read up on it some more before you start writing any code. There are a lot of existing tools out there that you can use to generate the lexing and parsing code for you once you've put the specifications into regex form. This youtube playlist is a pretty good spot to start.The book "Compiler Design" (ISBN-13: 978-0198066644) is also a good read and can be obtained for a reasonable price. 2 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted April 8, 2016 Share Posted April 8, 2016 Nice white paper Gip-Gip! I agree with Zack about considering first building a runtime library (Framework) and testing it's object set. You can write the compiler now to compile all of that syntactic sugar (which is very cool) in your intrinsics to asm, but need the runtime library to surface objects from it. The BASIC to C translator layer used by Jaguar BASIC has no runtime library, it is simply translated into C so a runtime had to be added and the objects surfaced to the BASIC afterwards. I think it's easier to build the language around the objects than to add them afterwards but there's no one set way to do it so if you're more motivated to write the compiler first I think you should. --- ascii art code sounds really cool, are you going to include a provision to use ascii art to draw sprites and screen bitmaps inline in AtaC source? Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 8, 2016 Author Share Posted April 8, 2016 --- ascii art code sounds really cool, are you going to include a provision to use ascii art to draw sprites and screen bitmaps inline in AtaC source? I would like to come up with a decent system for it, but I'm not exactly sure how to implement it(in other words, sometime in the future) Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted April 8, 2016 Share Posted April 8, 2016 I would like to come up with a decent system for it, but I'm not exactly sure how to implement it(in other words, sometime in the future) I used to include a header file with a bunch of constants defined like this: zz________ = %00000000; $0 0 zz_______X = %00000001; $1 1 zz______X_ = %00000010; $2 2 zz______XX = %00000011; $3 3 ... zzXXXXXX__ = %11111100; $FC 252 zzXXXXXX_X = %11111101; $FD 253 zzXXXXXXX_ = %11111110; $FE 254 zzXXXXXXXX = %11111111; $FF 255 which would let me to this: Digits: .byte zz____X___ ; ZERO .byte zz__XX_X__ .byte zz_XX___X_ .byte zz_X____X_ .byte zz_X___XX_ .byte zz__X_XX__ .byte zz___X____ .byte zz____X___ ; ONE .byte zz____XX__ .byte zz____XX__ .byte zz__X_XX__ .byte zz___XXX__ .byte zz____XX__ .byte zz_____X__ .byte zz____XXX_ ; TWO .byte zz_XXXX___ .byte zz__X_____ .byte zz___XX___ .byte zz_____X__ .byte zz__X___X_ .byte zz___XXX__ Nowadays I just use standard binary notation and created syntax rules so my programmers editor would colorize the binary values for me: Quote Link to comment Share on other sites More sharing options...
Joe Musashi Posted April 8, 2016 Share Posted April 8, 2016 For what it's worth, there is also a 6502 backend for LLVM:https://github.com/c64scene-ar/llvm-6502 I don't know if the code this generates is tight enough for the 2600 and LLVM might be a bit overblown for a project such as this, but it may be worth a look. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 9, 2016 Author Share Posted April 9, 2016 Now that development has started, I won't be posting anything big until some basic code generation is finished(or I come across a major flaw in the syntax and I have to restart all over again). After that development will continue over at GitHub. Quote Link to comment Share on other sites More sharing options...
Gip-Gip Posted April 19, 2016 Author Share Posted April 19, 2016 Just to keep everyone informed: Compiler development is running smoothly, as I work on it about 1-4 hours per day The major parts of code segregation are almost finished Code generation is planned out The project currently contains 15 files: main.c, main.h, getArg.c, getArg.h, replaceExt.c, replaceExt.h, compile.c, compile.h, memmang.c, memmang.h, getOp.c, getOp.h, enums.h, messages.h and Makefile 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.