www.retrosoftware.co.uk
http://www.retrosoftware.co.uk/forum/

Modest feature request
http://www.retrosoftware.co.uk/forum/viewtopic.php?f=17&t=356
Page 1 of 1

Author:  ThomasHarte [ Sat Sep 26, 2009 12:43 pm ]
Post subject:  Modest feature request

Hope I'm not asking a dumb question, but would it be possible to add some way for labels defined within a local (ie, brace enclosed) scope to be declared global? So you could have something like:
Code:
.DualPurposeFunction
{
   ...
.DualPurposeFunctionConstant:: ;double colon means symbol is global
   ora #00 ;to be dynamically reprogrammed to ora or eor
   rts
}

.SetPurpose1
   lda #&<hex for relevant ora>
   sta DualPurposeFunctionConstant
   rts

.SetPurpose2
   lda #&<hex for relevant eor>
   sta DualPurposeFunctionConstant
   rts

That's actually very close to what I want to do in my own code. I've a big lengthy function that has a heavily used inner loop and a lot of stuff around the outside. I want to change a few opcodes in the inner loop. The big lengthy function is called many times inbetween each opcode change, so it would noticeably cost extra if DualPurposeFunction reprogrammed itself upon entry each time rather than its current state being modal.

"You're being an idiot, you should achieve that by ..." is an acceptable answer to this request.

Author:  RichTW [ Sat Sep 26, 2009 5:09 pm ]
Post subject:  Re: Modest feature request

Heh... you're not the only one who wants something like this - I wanted to add it myself for exactly the same reason, but I couldn't come up with a syntax that I liked.

I don't like the double colon syntax, because it doesn't really stand out, it seems a little obscure, and also is already a perfectly legal construct in BeebAsm (basically an empty statement separated by colons).

I had a few possible options, none of which I particularly liked:

1) To provide a way of addressing local labels, rather than making them global, e.g.
Code:
.SomeRoutine
{
    LDA #0:STA &70
    .value LDA #0:STA &71
    RTS
}
        ...
        ...
    LDA #2
    STA SomeRoutine.value+1
    JSR SomeRoutine

This is a little odd though because it would require the new concept that the label SomeRoutine was somehow 'attached' to the braced section which followed.


1b) A variation on this would be to dispense with the idea that the top label was attached to the braces, and instead to say that any label defined with a further dot in its body is 'promoted' to global. Like this we could write:
Code:
.SomeRoutine
{
    LDA #0:STA &70
    .SomeRoutine.value LDA #0:STA &71
    RTS
}
        ...
        ...
    LDA #2
    STA SomeRoutine.value+1
    JSR SomeRoutine



2) To add an EXPORT keyword, which would create a global copy of a variable declared within the current scope:
Code:
.SomeRoutine
{
    EXPORT SomeRoutineValue

    LDA #0:STA &70
    .SomeRoutineValue
    LDA #0:STA &71
    RTS
}
        ...
        ...
    LDA #2
    STA SomeRoutineValue+1
    JSR SomeRoutine



3) Some leading character or something which would cause a label to be added in global scope:
Code:
.SomeRoutine
{
    LDA #0:STA &70
    .$SomeRoutineValue
    LDA #0:STA &71
    RTS
}
        ...
        ...
    LDA #2
    STA SomeRoutineValue+1      ;or maybe STA $SomeRoutineValue+1
    JSR SomeRoutine


They all seemed a little contrived and horrible though. What do you think?

On the whole, I quite liked the brace syntax for marking local blocks of code, as it had familiar roots (from C-type languages), and was far more clear than the the method for declaring local labels that most assemblers resort to (a numeric value prefixed by + or -, yuk!)... but it does come with this problem that everything within becomes hidden to the outside world. Not a problem in C, but assembler's much more dirty!

I'll be happy to add this facility once we can reach some consensus amongst those who use the tool as to how it should be done!

Author:  ThomasHarte [ Sun Sep 27, 2009 1:05 pm ]
Post subject:  Re: Modest feature request

The double colon wasn't a serious suggestion, and you are completely right that it is ambiguous, obscure and lacking in visibility.

Of your suggestions, I like the EXPORT keyword the best, though possibly it should just promote the label a single scope rather than always hopping all the way to global?

Author:  ThomasHarte [ Mon Sep 28, 2009 6:29 pm ]
Post subject:  Re: Modest feature request

Actually, further to that maybe one keyword to promote a label a single scope and an alternative option that always promotes it all the way to global? Otherwise I guess you'd potentially need to export a symbol more than once, which is getting a bit contrary to the don't repeat yourself principle and also likely to be annoying if you ever change the name of the symbol.

Author:  FrancisL [ Tue Sep 29, 2009 1:03 pm ]
Post subject:  Re: Modest feature request

Personally I think it is bad practice to declare anything as global from within a procedure or subroutine. It makes keeping a track of things a potential nightmare!

IMHO globalised items should be declared at the start.

Kind regards,

Francis

Author:  RichTW [ Tue Sep 29, 2009 6:39 pm ]
Post subject:  Re: Modest feature request

Francis, in the context of a high- or medium-level language, I would agree with you completely! But assembler's a more dirty beast, and on a regular basis you have to do things that'd make a high-level programmer wince, just to squeeze a bit of extra performance.

Amongst these kind of things are the kind of self-modification of the innards of a subroutine, as Thomas suggested. While BeebAsm attempts to dress up its source code with this high-level-esque scoping of labels, unfortunately in this situation we need to break all the taboos and provide a way to promote a local label to global scope :)

Any other thoughts on the best syntax for this from anyone who uses it?

Author:  FrancisL [ Tue Sep 29, 2009 9:02 pm ]
Post subject:  Re: Modest feature request

True, I'm forgetting that assembler can be, as you put it, a more dirty beast especially when you are trying to cram as much as you can into the likes of a BBC! :D

Kind regards,

Francis

Author:  MartinB [ Wed Sep 30, 2009 10:26 am ]
Post subject:  Re: Modest feature request

I've followed this with interest and thought I'd dare to suggest...

How about using an asterisk prefix which in many applications means 'wild' and therefore, albeit tenuously, global?

Code:
.SomeRoutine
{
    LDA #0:STA &70
    .*SomeRoutineValue
    LDA #0:STA &71
    RTS
}

Also, if Thomas needs a single scope promotion, you could use a caret which loosely means 'raise' in maths and the symbol does suggest this?
Code:
.SomeRoutine
{
    LDA #0:STA &70
    .^SomeRoutineValue
    LDA #0:STA &71
    RTS
}


Martin

Author:  ThomasHarte [ Sun Oct 04, 2009 2:07 am ]
Post subject:  Re: Modest feature request

My only consequential thought is that if scope promotions are going to be built into the label definitions rather than declared as a separate property, you'll need to be able to declare an arbitrary degree of promotion. E.g. ^Label to declare a label that is promoted a single scope, ^^Label for promotion to two scopes up, etc. And I quite like a shorthand like *Label (or maybe ^*Label, as though it just means "raise as many times as possible"?) to promote a label all the way to global.

I suppose an alternative idea would be to allow symbols to be exported from one scope (to some sort of symbol table) and subsequently imported to arbitrarily many others. Probably not a sufficiently useful variation to justify the syntax overhead as things stand (though one block of code with its own scope could be modified by another without polluting global scope), but possibly useful if there was a new INCLUDE-style statement that just said "pretend you've assembled this but don't actually generate the code, just keep the export symbols", as it'd make multiload titles a lot easier to manage. Though I'm on iPhone, so can't check there isn't already something like that.

Having thought it out as I type, my favourites are caret and asterisk as above, with an INCLUDE-style statement that will do a pretend assemble of another file, then copy the labels in its global scope to the includer's current scope. If there isn't already such a directive.

And, yes, I'm aware that the request is getting ever less modest... sorry!

Author:  RichTW [ Sun Oct 04, 2009 8:37 am ]
Post subject:  Re: Modest feature request

Ok then, Martin is the winner of the prestigous "BeebAsm Symbol Scoping Syntax Design" award. Congratulations :) I hope you can handle the fame, money, fanmail, etc.

I quite like the idea of using ^ and * in front of the label you define - it's unobtrusive syntax, nice and concise, but stands out as it need to. And it makes sense!

Personally, I have never nested one scope within another, so I would only need * for myself, but I'll properly implement any number of ^s to move it up a level.

Regarding just defining symbols and not generating code, there's not really any need for this in BeebAsm. You can just put a SAVE at any point in the source file, and it'll assemble what's there so far. Then use CLEAR to clear the block of memory you're about to use, assemble new code there, and put another SAVE statement. This was designed like this to make overlays very simple, because the symbols are never cleared out. See the example on the wiki about assembling a game which lives in a number of paged ROMs to see how this would work. By wrapping each overlay in braces, and then using this new syntax to define global labels, you could ensure that the 'namespace' of each overlay was not polluted.

Author:  MartinB [ Sun Oct 04, 2009 11:18 am ]
Post subject:  Re: Modest feature request

:shock: Gosh, it feels like I've just got a fingertip onto the platform of the clever guys!

Actually, there's a tale behind my suggestion so now at the risk of my getting that fingertip stamped on, pull up a sandbag...

Some considerable years ago, I was involved in using and customising a Motorola 6800 assembler because we (the defence suppliers) used single board 6800 cards as built-in-test (BIT) modules in several bits of kit. When the product was eventually delivered to the customer (the Services), their guys took over any further bespoke development using the tools we also supplied. This very topic cropped up and this is the syntax we used. However, they came back and said that when their internal auditors were inspecting the BIT code, their only worry was that counting carets (sounds odd) was inviting trouble. Hence, we finally went for the same symbols but immediately encased in square brackets which then meant we could also add other label specific prefixes too and all would be tightly identifiable. (Being more on the hardware side, I wasn't writing the assembler, just using it and advising, but the long-suffering tools developers reckoned this made it easier for the parser too.) We were then also able to take full advantage by using letter markers such as [T] for time critical where the item could only be written to inside an interrupt routine and [S] for safety critical items which would be assembled to protected memory and could not be written to by hardware front panels - you get the idea. Coincidentally again, we also used syntax such as [FX8,7]variable in declarations to identify the use of fixed point items such as you (Rich) have been describing elsewhere.

Anyway, assuming you're still awake, for our (your) two examples we would actually have used the following...

Code:
SomeRoutine
{
    LDA #0:STA &70
    .[*]SomeRoutineValue
    LDA #0:STA &71
    RTS
}


Code:
.SomeRoutine
{
    LDA #0:STA &70
    .[^3]SomeRoutineValue             ; e.g.promote three levels
    LDA #0:STA &71
    RTS
}


I'm probably pushing my luck now but thought I'd share the story anyway :)

Martin

Author:  ThomasHarte [ Sun Oct 04, 2009 12:22 pm ]
Post subject:  Re: Modest feature request

Quote:
Personally, I have never nested one scope within another, so I would only need * for myself, but I'll properly implement any number of ^s to move it up a level.

Having though a bit more, I think [single] nested scope is actually the neatest way to express the type of code I originally asked about:

Code:
;
;   begin block of related routines
;
{
.*DualPurposeFunction   ; a global, intended for use outside of the block
{
   ...
.^DualPurposeFunctionConstant ;something that other routines in the block are interest in
   ora #00 ;to be dynamically reprogrammed to ora or eor
   rts
}

.*SetPurpose1
   lda #&<hex for relevant ora>
   sta DualPurposeFunctionConstant
   rts

.*SetPurpose2
   lda #&<hex for relevant eor>
   sta DualPurposeFunctionConstant
   rts
}

;
; So:
;
;   DualPurposeFunction, SetPurpose1, SetPurpose2 all global
;
;   DualPurposeFunctionConstant visible inside that set of routines only
;

Quote:
I'm probably pushing my luck now but thought I'd share the story anyway

Obviously that's more something for RichTW to comment on, but I can see what they mean — even just ^^^ is arguably not as concise (visibly, anyway), as unobtrusive or as clear as [^3].

Page 1 of 1 All times are UTC [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/