Menu

#60 64tass r2496 produces error when first item in list is on a separate line

1.56.2625
open
nobody
None
5
2021-12-13
2021-10-24
Tom Seddon
No

Looks like list parsing changed at some point. The attached file builds fine with 64tass r2495, but produces a "an expression is expected" error with r2496 after the opening square bracket.

Build with just "64tass test.s65".

Found this after upgrading 64tass and trying to build my code: https://github.com/tom-seddon/beeblink/blob/edb12b36d950ddd1ebb51d85289b6d053fda9337/rom/beeblink.s65#L3219

Was this change intentional?

Thanks,

--Tom

1 Attachments

Discussion

  • Soci/Singular

    Soci/Singular - 2021-10-25

    Yes, I'm sorry and I must admit it was not a mistake.

    Back in 2013 I thought that it'd be nice if one could span expressions into
    multiple lines. Like a lot of assemblers 64tass is line based by design but
    that didn't stop me from hacking the expression parser to process the following
    lines until the expression was complete. It seemed to work at first. What could
    possibly go wrong?

    Well, quite a lot. Over the years I tried to fix all the breakage but quite a
    lot remained.

    In many cases by the time an error needs to be reported the current line was
    "gone" and it was a different one already. In some cases I could make it work but
    not everywhere and there was no easy way around it. This was especially
    problematic within macros where replacements happened.

    It didn't quite work well with listing as by the time the data to be listed was
    available all the previous lines were long gone and only the last was available
    so such expression got truncated.

    There were tons of problems with directives like ".for" if such a multi line
    expression was used there due to the way they operate. After a lot of fixing at
    least it didn't crash.

    Whenever I tried to use such expressions it didn't play well with the syntax
    highlighting or automatic indentation I normally use. So even if I thought it'd
    be useful somewhere at the end it was rewritten differently anyway.

    What isn't possible either with them is fault tolerant parsing. And not much
    can be done about that as there's no definite ending like the semicolon in some
    languages. In short if one forgot a ")" or "]" somewhere that usually resulted
    in tons of garbage diagnostics as the rest of the source became part of the
    expression.

    I thought that such silly mistakes are rare anyway so that's not a problem but
    then was reminded several times by others that maybe it matters more than I
    expected.

    So before the last release I made took the hard decision to give up on multi
    line expressions. It's more complicated than I thought and I couldn't make it
    work properly over the years even where it's theoretically possible.

    The feature itself was never officially documented as it was an unfinished
    experiment. Some figured out it's existence anyway and used it. All I can say
    is I'm very sorry it didn't work out and this caused breakage now.

    The work around is that such multi line expressions need to be broken up.
    Specifically for long lists I do this:

    _           := [ irq1, signs.irq2, signs.irq3, signs.irq4, minimap.irq1 ]
    _          ..= [ minimap.irq2, minimap.irq3, ship.irq1, minimap.irq4 ]
    _          ..= [ minimap.irq5, minimap.irq6, signs.irq5, signs.irq6 ]
    _          ..= [ signs.irq7, irq2, signs.irq8 ]
    irqs         = _    ; long list of IRQ routines above
    
    _           := ["  #      #  "]  ; use temporary "_" local label
    _          ..= ["   #    #   "]  ; add more elements
    _          ..= ["  ########  "]
    _          ..= [" ## #### ## "]
    _          ..= ["############"]
    _          ..= ["# ######## #"]
    _          ..= ["# #      # #"]
    _          ..= ["   ##  ##   "]
    invader1     = _                 ; set up constant from finished list
    

    The first line of broken up list is stored into a temporary local variable
    called "_" using ":=" so that the following lines can extend it using "..=". At
    the end it's stored into a properly named constant which can be accessed by
    code above it.

    Sort of verbose I know but it works. The same method can be applied to split
    long strings over multiple lines as well.

     
  • Tom Seddon

    Tom Seddon - 2021-10-27

    Thanks for the response!. I'm not too bothered about multi-line expressions generally, but I'm a bit sad about not being able to concisely split a list over multiple lines any more :( That's just my immediate reaction though... I'll probably get used to it after a while.

    Main thing I use this for: building up lists of labels, one per line, for later use with .byte <values/.byte >values for separate lo/hi tables. Possibly using values-1 to make the table RTS-friendly.

    What about some kind of non-expression syntax for building lists? For example, instead of this:

    tape_and_rom_dispatch_fsc_routines=[
                    LA422,          ;0 - *OPT
                    LA4F1,          ;1 - EOF
                    LA110,          ;2 - */
                    LA129,          ;3 - unknown * command
                    LA110,          ;4 - *RUN
                    LA168,          ;5 - *CAT
                    L9F3A,          ;6 - shut down FS
                    L9F9E,          ;7 - obtain file handle range
                    L9F3A,          ;8 - OS command
                    LA155,          ;9 - *EX
                    L9F3A,          ;10 - *INFO
                    LA113,          ;11 - *RUN command for library
    ]
    

    something like this:

    tape_and_rom_dispatch_fsc_routines: .beginlist 
                    .item LA422          ;0 - *OPT
                    .item LA4F1          ;1 - EOF
                    .item LA110          ;2 - */
                    .item LA129          ;3 - unknown * command
                    .item LA110          ;4 - *RUN
                    .item LA168          ;5 - *CAT
                    .item L9F3A          ;6 - shut down FS
                    .item L9F9E          ;7 - obtain file handle range
                    .item L9F3A          ;8 - OS command
                    .item LA155          ;9 - *EX
                    .item L9F3A          ;10 - *INFO
                    .item LA113          ;11 - *RUN command for library
                    .endlist
    

    .item would accept any value(s), and add them to the list being built up (obviously the expression(s) would have to be all on one line). I suppose you could allow the use of the various data directives (.byte, .text, etc.) for inserting specific types.

    .item doesn't save any bytes over _..=, but the syntax is the same for every element.

    Other ideas, that I don't think are too important to me:

    Maybe allow labels "inside" the list, that would be scoped like inside a block, that are the index of that position in the list?

    Not bothered about nested lists with this syntax but maybe that could be an option too.

    Thanks,

    --Tom

     
  • Kruthers

    Kruthers - 2021-12-13

    Hey Soci, it turns out I'm one of those that figured out this unknown feature and used it quite a bit, heh! Was confused by all the error messages for a few minutes after upgrading. But no worries, the last thing I want to do is guilt-trip or stress you out for thanklessly building a tool that I love using. I understand the predicament...

    But if I could make another suggestion after Tom's, how about the classic Unix line continuation trick of ending a line with a backslash to mean it's always combined with the next line? I know, it's pretty ugly, I never really liked it... And it probably doesn't really solve your problem of parsing stuff line based. Plus it probably directly conflicts with inline comments which is kind of the point of multiline expressions. Ug... guess I'm grasping at straws here.

    Anyway, thanks for the workaround suggestion above, that will at least work!

     

Log in to post a comment.

MongoDB Logo MongoDB