Jump to content
Kaj de Vos

A new language for the Atari

Recommended Posts

Greetings and felicitations, children of technology!

 

A few of you may know me from around three decades back. I have to congratulate you all on this cool forum, that has amazing activity. I am happy that the community is still there. I am contacting the community again, because I am doing some work on Atari again. I am making a new programming language, that will be general-purpose, but that I am targeting at 8-bit Atari first.

 

Most new languages don't target the old machines. There are a few exceptions, but they target the vintage machines specifically, and are not meant as general-purpose languages for modern systems. I think this is feeble and probably wrong in terms of language design: there are many bad reasons, but no good reason to not support small systems. C is still used everywhere, and it can do it. I think any new language should improve on C; it should not be less capable. I always thought this should be possible, and it is turning out to be true. At first I thought it would be harder to support the old systems, but it actually turned out to be easier, and it helped get the project off the ground. Small systems are much easier to work for due to less complexity, they are more motivating, they provide meaningful results earlier, they keep you aware of performance and they prove you can target very small devices, such as for Internet of Things. Like how Contiki became an IoT operating system starting on C64.

 

I have wanted to do this language for some three decades, but the industry became ever more complex faster than I could master it. Every time I thought I could improve some things, the platform I was using was already outdated. For a quarter century, I didn't really know how to improve languages on the newest platforms, so I tried to use the best ones I could find. Yet almost every time I wanted to do a project or a commercial assignment and needed the platform and language to just work, I ran into walls that debilitated my efforts. This was all the more frustrating because there once was a system that I could do anything on that I wanted: my trusty Atari 8-bit. Perhaps my projects are too ambitious, yet this was no problem on Atari. I desperately need that power and control back, and in the past years, the puzzle pieces started to come together. Now it's a matter of doing the enormous amount of work required from a modern language. I am half a year into the project, and am double as productive as I have ever been.

 

The language is mostly inspired by REBOL, of Amiga heritage:

 

https://en.m.wikipedia.org/wiki/Rebol

 

REBOL has great clarity and conciseness of expression, and a great capacity for abstraction, which can be used to define cross-platform abstractions. It has been measured to be the most expressive general-purpose programming language:

 

https://redmonk.com/dberkholz/2013/03/25/programming-languages-ranked-by-expressiveness/

 

Among others, I was further inspired, for their performance and support of native Atari functionality, by Action!:

 

https://en.m.wikipedia.org/wiki/Action!_(programming_language)

 

and by PL65:

 

https://atariwiki.org/wiki/Wiki.jsp?page=PL65

 

The language is past the proof-of-concept stage, but it is still very incomplete. On the other hand, it will match features expected from an 8-bit language before it will be able to match expectations for a modern language. I am working on a sneak preview release to let people try it. I will post examples as I go, if you like. After the sneak preview I will be working further on a crowd-funding website, where you will be able to influence the development through donations.

  • Like 9
  • Thanks 1

Share this post


Link to post
Share on other sites
Hello, world!
 
 
Here is the obligatory Hello World example:
 
print/line "Hello, world!"
 
It is easy to get started, like we are used to in the old languages such as BASIC. There is no boilerplate code required such as in many other languages.
  • Like 3

Share this post


Link to post
Share on other sites
Fibonacci numbers
 
 
Here is a version of the well-known example that computes Fibonacci numbers:
 
; Maximum 23 for integer16! result
; Max 46 for integer32! result
parameter= 23
 
print "Fibonacci "  print parameter  print ": "
 
either parameter <= 1 [
Fibonacci: parameter  ; Fibonacci 0 ... 1
][
Fibonacci: previous: 1  ; Fibonacci 2
 
loop parameter - 2 [
previous: also
Fibonacci
Fibonacci: Fibonacci + previous
]
]
 
print/line Fibonacci
 
It doesn't declare the type of the variables FIBONACCI and PREVIOUS, so they are inferred to be of INTEGER! type, which is a signed value defined as 16 bits on 8-bit machines. The maximum Fibonacci value that can be computed with this is that of parameter 23.
 
parameter= 23
 
declares this as a constant that fits in a BYTE! type. Note that the = is part of the word: there should be no whitespace between them.
 
ALSO A B is a shorthand for, in this case:
 
let safe integer! a
b
safe
 
for a situation like here, where statement B modifies A but the previous value of expression A is still needed.
 
 
Fibonacci numbers are unsigned, so we can optimise this program by declaring the variable types explicitly as unsigned integer numbers of the NATURAL! type:
 
; Maximum 24 for natural16! result
; Max 47 for natural32! result
parameter= 24
 
print "Fibonacci "  print parameter  print ": "
 
natural! [Fibonacci previous]
; natural32! [Fibonacci previous]
 
either parameter <= 1 [
Fibonacci: parameter  ; Fibonacci 0 ... 1
][
Fibonacci: previous: 1  ; Fibonacci 2
 
loop parameter - 2 [
previous: also
Fibonacci
Fibonacci: Fibonacci + previous
]
]
 
print/line Fibonacci
 
This enables us to compute larger Fibonacci values. Note that ALSO A B adapts to this situation by coming to mean:
 
let safe natural! a
b
safe
 
On larger machines, NATURAL! and INTEGER! are larger and the same code can compute even larger Fibonacci values. To compute larger Fibonacci values on Atari 8-bit, the variables FIBONACCI and PREVIOUS can be explicitly declared as NATURAL32! type, which is 32 bits unsigned.
  • Like 1

Share this post


Link to post
Share on other sites

Nice. It would be interesting to see the benchmark results from the suite that is being currently used by the MADS/Mad Pascal/K65 folks.

Share this post


Link to post
Share on other sites

I would say that an unsigned 24 or 32 bit datatype was a necessity these days, to deal with things like larger disk drives. The ability to locate the compiled code at a certain address would also be useful. So far, most of these new languages seem not useful mainly due to lack of ordinal types larger than 16 bits.

  • Like 1

Share this post


Link to post
Share on other sites

I just went down a Rebol rabbit hole but came up more or less dry. The ideas sound good, but the implementation looked stale. Enter Red.

 

You may already be familiar, but perhaps it's instructive to also check out Red in addition to Rebol. It's the heir apparent, and this overview explains why Rebol died and why Red is the next best thing: 

Quote

REBOL didn't gain traction, because the implementation was closed, inadequate (no mobile OSes, little 3D and primitive audio support) and now is way behind. Red is there to solve that.

 

Share this post


Link to post
Share on other sites

Thanks! 🙂 It's exciting to see the response.

 

It would indeed be nice to compare with benchmarks for other languages. I'm preparing a few benchmarks, but I can't duplicate all the benchmarks in existing suites. This would be a nice project for others once I have provided a release.

 

The language has multiple code generator backends. Currently the most developed one is the one that generates C, to target as many platforms as possible. The Atari code is currently generated by CC65. CC65 doesn't generate the best code, but the C that I generate is fairly heavily optimised to force CC65 to generate better code. I am using CC65 as a baseline for all other possible C platforms. So the performance that can be expected is roughly that of C by CC65.

 

CC65 has an option to change the start address of the code, so this will be possible, eventhough it's not as flexible as an assembler.

 

I would like to do a native Atari code generator backend someday, to improve performance and flexibility. This will also depend on funding.

 

I have preliminary 24-bits types in the language. I thought that was a pedantic idea of mine, but apparently I'm not the only one who wants them. 🙂 C doesn't support them, so it will take extra effort to actually implement them. In general, I will implement all the low-level types that C has, and all the high-level types that REBOL has. This fixes the dichotomy in Red, which is torn between the high-level Red language and the low-level Red/System language.

 

Red was launched on a REBOL conference of mine in the Netherlands. I helped launch the language and contributed to it for half a decade. After that I left the project, because I am disappointed that it hasn't fulfilled its promises.

 

Before all that, I contributed to the latest version of REBOL and lobbied its creator Carl Sassenrath to open-source it. It eventually was, and REBOL could have done most of what Red promised, but Carl abandoned it when his funding ran out. After the leader left, the project was torn apart by competing interests.

 

My language is meant to succeed both REBOL and Red.

  • Like 1

Share this post


Link to post
Share on other sites

You got me on a first mention of Rebol :)

 

Can't wait to see it running on atari!

 

  • Like 1

Share this post


Link to post
Share on other sites
13 hours ago, Alfred said:

I would say that an unsigned 24 or 32 bit datatype was a necessity these days, to deal with things like larger disk drives. The ability to locate the compiled code at a certain address would also be useful. So far, most of these new languages seem not useful mainly due to lack of ordinal types larger than 16 bits.

I think it's very specific case when you need 24 or 32bit datatypes on 8bit. I released a lot of programs for Atari XL/XE in recent years and never needed them. Instead of adding it as a language feature probably could be enough to have a short asm lib for handling large drives or for long ints operations.

 

  • Like 1

Share this post


Link to post
Share on other sites

Rainbow

 

Here is a version of the classic rainbow demo, specific for Atari 8-bit:

 

unsafe!!! constant reference volatile byte! [
    ; OS

    RTCLOK3= ~14

    ; ANTIC

    COLPF2=  ~D018
    WSYNC=   ~D40A
    VCOUNT   ; ~D40B
]

forever [COLPF2: WSYNC: overflow VCOUNT + RTCLOK3 << 1]

 

Hexadecimal literal numbers are supported, but preceded by a ~. The $10 notation means money in English and in REBOL, and I want to support that instead of override it.

 

The above style of (address) declarations is in enumeration form: values can be left out if they are consecutive.

 

I intend to design a safe language, like REBOL. Checks are not implemented yet, but overrides will eventually be needed to enable unsafe behaviour. Defining literal memory locations is unsafe, so the definitions are enabled by the unsafe!!! keyword. It's not really a keyword, but a method, like all function applications. More on that later.

 

This is a cyclic demo, where VCOUNT and RTCLOK keep counting, so the byte result computed to be put in COLPF2 will also wrap around regularly. In more common programming, we want the language to error out on such an overflow of a computation, but not in this hardware programming. So we wrap the expression with the overflow method.

 

Evalution order of operators in expressions is simply left to right. There is no precedence order to memorise, not for you and not for the compiler. When you need a different order, you can use parentheses.

  • Like 2
  • Haha 1

Share this post


Link to post
Share on other sites

Assembly


I loved the integrated assembler in PL65, so I implemented one, too. The above rainbow demo can also be written as:

    unsafe!!! [
        constant reference volatile byte! [
            ; OS

            RTCLOK3=    ~14

            ; ANTIC

            COLPF2=        ~D018
            WSYNC=        ~D40A
            VCOUNT
        ]

        forever:
                LDA VCOUNT
                CLC
                ADC RTCLOK3
                ASL-A
                STA WSYNC
                STA COLPF2
            CLC
            BCC forever
    ]

 

Assembly is unsafe, so it needs to be wrapped within unsafe!!!.

 

Of course, this is thoroughly specific to 6502 and Atari, and non-portable.

 

Note that using the same name FOREVER for the assembly label as the built-in FOREVER loop in the previous example is no problem. It just means that in this scope, FOREVER now refers to the label. It does mean that the FOREVER loop method can't be used anymore in the same scope.

 

Also, there is no conflict between the notations for setting a value A: B and defining an assembly label "C: NOP". The language sees the difference like we humans do. This would change if you were to redefine NOP: D. This wouldn't change the definition of the built-in assembly instruction NOP itself, but it would change the meaning of the word NOP in the local scope to a normal variable, referring to value D. The language would process that just fine, but it would become confusing for humans, so better not do such things. On the other hand, if you are oblivious to 6502 assembly, it's no problem if you ever use a variable name that happens to be the same as a built-in assembly instruction, or any other built-in method.

 

To be precise, LABEL: NOP is similar to setting a value in that it defines a re-assignable label (at compile time). It looks like what we're used to in most assemblers and in C, but labels are normally fixed, so it's safer to write LABEL= NOP which defines a constant label that can't be re-assigned in the same scope.

 

In general, it's best to default to defining words as constants (NAME= VALUE) unless they need to be changed as variables in the program (NAME: VALUE). Constant (immutable) values make the program safer. Compile-time constant values and even constant expressions (NAME= CONSTANT-1 + CONSTANT-2) help the compiler to generate more optimised code. This easy distinction is inspired by the classic ALGOL 68 language (which uses = and :=):

 

https://en.m.wikipedia.org/wiki/ALGOL_68

Edited by Kaj de Vos
Don't want the automatic smiley
  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites

I understand the concept, but I resent the idea of labeling anything I code as unsafe. I don't see the need to use dramatic adjectives in order to indicate that I'm dealing with code blocks that aren't part of the language proper, may have some potential for unintended consequences (any code has the potential for unintended consequences), or aren't portable. I've always programmed with the idea that you can ultimately do no real harm -- aside from the potential of writing to disk and destroying data, which shouldn't be a problem for anyone who has some sense about safeguarding code and data. The whole practice feels... childish... laughable...

 

Edited by MrFish

Share this post


Link to post
Share on other sites

There are two sides to this.

 

36 Years ago, when I got my Atari, I had similar feelings. When I learned POKE addresses and machine code, I wondered for a while why so much wasn't protected. Then I realised that on a train station, nothing was stopping you from stumbling in front of a train, either, so it was up to you not to do that. In comparison, a crashing computer is not a big deal.

 

On the other hand, keep in mind that this language is meant to scale to all machines and most any problem domain, so it will be different from other 8-bit languages. Not all progress since then is positive, but languages and operating systems have become more careful of safety, and I think that is a good thing. It won't matter much for small programs by single authors on 8-bit hobby platforms, but it does matter for large, commercial software systems developed by teams using libraries from third parties. The provisions for that need to be in the language, so they will also be there on 8-bit.

 

As a compromise, for example, I decided to only require definitions of memory addresses to be marked unsafe, and not their use. This means that the programmer can normally import predefined definition libraries, and when the library is trusted, the definitions can be used without further precautions.

 

In other languages, embedding assembly usually requires something like an ASM clause. unsafe!!! is a different word, but the effort is the same.

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, MrFish said:

The whole practice feels... childish... laughable...

The distinction between safe and unsafe code in modern language design is definitely not something new. Rust: https://en.wikipedia.org/wiki/Rust_(programming_language) Since 2010. But the ideas  behind it have been around since the days of the Ada programming language (used by NASA, etc...) I think your comment deserves the same qualifications you used yourself. Emphasize is mine ;)

Share this post


Link to post
Share on other sites

Yes, I saw the unsafe keyword in Rust. It's a modern system programming language, and I want to be able to do the same things. I wanted to make a distinction with overflow which is more about changing behaviour, less dangerous. REBOL has the convention to suffix type words with a single ! so that was already taken. It's good practice to mark dangerous places in source code with something dramatic in a comment, so why not standardise that in the code itself.

Share this post


Link to post
Share on other sites
7 hours ago, Kaj de Vos said:

Then I realised that on a train station, nothing was stopping you from stumbling in front of a train, either, so it was up to you not to do that. In comparison, a crashing computer is not a big deal.

 

Crashing a computer is not only "not a big deal", it's very often part of the normal development process as new code is being tested.

 

7 hours ago, Kaj de Vos said:

On the other hand, keep in mind that this language is meant to scale to all machines and most any problem domain, so it will be different from other 8-bit languages. Not all progress since then is positive, but languages and operating systems have become more careful of safety, and I think that is a good thing. It won't matter much for small programs by single authors on 8-bit hobby platforms, but it does matter for large, commercial software systems developed by teams using libraries from third parties. The provisions for that need to be in the language, so they will also be there on 8-bit.

 

I didn't realise you were targeting such a wide audience. So, I agree that the consideration makes sense.

 

7 hours ago, Kaj de Vos said:

In other languages, embedding assembly usually requires something like an ASM clause. unsafe!!! is a different word, but the effort is the same.

 

I understand using "ASM" for embedded assembly language, and I understand why it's desirable to flag ASM as being potentially incompatible from one system/platform to another; I also understand having the ability to go outside of well-defined language constructs, programming API's, or trusted libraries has the potential for unintentional consequences or system instabilities. But to have an across-the-board branding of "unsafe!!!" makes it sound as if it's something one shouldn't do at all; and yet, there the construct exists in the language to be used, and in fact is often necessary (hence the reason it exists in the first place). I know part of the point is that it will naturally cause the programmer to be more cautious; but in my opinion at the cost of less clear language terminology (other than the overly-emphatic clarity about the need for caution).

 

Potentially unsafe... maybe. I think some more fitting terms would be: language independent, library independent, unsupported, non-standard, autonomous, or unconventional.

 

6 hours ago, ivop said:

The distinction between safe and unsafe code in modern language design is definitely not something new. Rust: https://en.wikipedia.org/wiki/Rust_(programming_language) Since 2010. But the ideas  behind it have been around since the days of the Ada programming language (used by NASA, etc...) I think your comment deserves the same qualifications you used yourself. Emphasize is mine ;)

 

I understand this isn't some new idea. He already stated the influence of ALGOL 68. I'm not unfamiliar with the practice/concept, as I stated at the beginning of my first sentence.

 

So, it's inherently childish and/or laughable to question any practice that's been around for X number of years?

 

6 hours ago, Kaj de Vos said:

It's good practice to mark dangerous places in source code with something dramatic in a comment, so why not standardise that in the code itself.

 

This is exactly what I mean: it's dangerous to use ASM when it's called for?

 

"Unsafe!!!" sounds like something you'd put on a sign in front of a bridge that shouldn't be used anymore.

 

Edited by MrFish

Share this post


Link to post
Share on other sites

Ah c'mon now. Let's not lead this thread into a 10 page bikeshedding about things like syntax. I'm sure what we're all most interested in is to see what features this language have in order to solve real problems with it. If people start arguing about largely insignificant things like keyword naming (and hey, the language is still in development, things can change) then many will lose interest, possibly including the language's author.

 

All I'm saying is: maybe we should wait a bit until we can see more big/serious/complex examples of what this language has to offer before anything else :).

  • Like 2

Share this post


Link to post
Share on other sites

@ggn - very good point.

 

It would be also useful to explain more the target audience of the language. Is it for the beginners? Is it to be the fastest one (games) or the easiest to read, or with a lot of boilerplate to assure safety (eg bigger group projects)? Is it aiming to include some new language concepts never seen before or be friendly to users of specific language? My personal opinion is that "safety" is hardly sellable on 8bit platform as key feature.

Edited by ilmenit
  • Like 1

Share this post


Link to post
Share on other sites

wow!   i was big time into writing rebol.  

 

and integrated assembler. how does zo much interesting stuff halpen bere!!!

 

well I have to check this out soon

  • Like 1

Share this post


Link to post
Share on other sites
51 minutes ago, ilmenit said:

Is it for the beginners? Is it to be the fastest one (games) or the easiest to read,

1. From my perspective it doesn't look like it's for beginners, I can hardly make sense of the code. 

2. Could be, yet to be seen.

3. Again as I already said, it's almost meaningless to me. (maybe I'm stuck with the tried and tested languages :) ) 

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...