Brass 3.0.0.0 Beta 13

One suite to code them all. An complete IDE and assembler for all your z80 projects!

Moderators: benryves, kv83

Post Reply
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

What would happen if you tried to redefine an instruction that way?
If, for example, instead of "load" you had defined "ld"..
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Of course, I'm being silly.

This wouldn't work for functions (governed by the rules of the compiler and expression parser) but it would work for macros, which just perform direct replacement of tokens when a particular name is hit.
User avatar
driesguldolf
Extreme Poster
Posts: 395
Joined: Thu 17 May, 2007 4:49 pm
Location: $4080
Contact:

Post by driesguldolf »

About name confusion, What about some naming precedence, like:
if a name is used double, show a warning, and use the one with the function highest on this list:
  • Instructions
  • Functions
  • Macros
  • Labels
Yes I suspected some unprocessed exception, but I was thinking from the pov of someone who never heard of .NET :P
I may not be fully qualified, but I do know what a stylesheet is :mrgreen:

I haven't got my hands dirty on macros and functions yet, so here I go :D

Where can I find a list of all build in functions? EDIT: ofcourse plugin site... I need to look better...
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

driesguldolf wrote:About name confusion, What about some naming precedence, like:
if a name is used double, show a warning, and use the one with the function highest on this list:
  • Instructions
  • Functions
  • Macros
  • Labels
Macros are processed whilst the code is being read out of the source files (this is why we can bend the rules for them a bit). :) Note that #macro isn't a "true" macro, it's just a function where the arguments default to macro replacement (so #macro(x) is the same as #function(macro x)).

The way the compiler works is that it starts with a string of tokens, like this:

Code: Select all

label = 1 xor a
It starts from the left, and calls a function in the assembler plugin to try and match the code (so the assembler gets "label = 1 xor a", sees that's not valid, and returns false). It then moves on to the next token (" = 1 xor a", returns false), then the next ("1 xor a") before seeing "xor a" and returning true.

At this point the compiler knows that "label = 1" is the label assignment component of the statement, and "xor a" is the assembly instruction itself.

(To further complicate issues, "xor a" can also be a directive, but directives are easier to spot as they start with a "." or a "#").

Now it knows what the two parts of the statement are, it evaluates the expression on the left, then passes the code on the right to the assembler plugin (or directive, if it's a directive).

This, coincidentally, is why indentation doesn't matter in Brass. It also is why this is a bug:

Code: Select all

label bcall(x) ; doesn't work properly.
label .bcall x ; works properly.
bcall() is a function, thus part of an expression (and not an instruction or directive) so gets evaluated next to "label". .bcall is a directive, so is handled correctly.

This will be fixed by marking certain functions as being instructions rather than as components of expressions. The marker is already there (note how bcall(x) builds but abs(x) on its own returns an error as no assignment is made).
Yes I suspected some unprocessed exception, but I was thinking from the pov of someone who never heard of .NET :P
I may not be fully qualified, but I do know what a stylesheet is :mrgreen:
I was being silly, it's a bad error message due to some lazy programming on my behalf.
Where can I find a list of all build in functions?
In the help viewer, under "Functions". If, like me, you like your documentation off-line rather than on-line, Start->All Programs->Brass->Brass Manual.

Note that there have been several architectural changes since a lot of those have been written, so they might not all work properly. :)
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

I've added scripting support (eg C# and VB script, but should work with any .NET language). It's a little incomplete at the moment (no easy interop between .NET objects and Brass, so you're limited to passing strings and numbers around) but it works. WinForms Test shows one potential (and rather silly) use of this new system (just build the project file to see what I mean). ;)

I also added documentation comments to over 200 public methods, properties and fields that were missing them.
Brass 3.0.0.0 Beta 5 wrote:New internal source statement layout (linked list rather than fixed indexing) means that statements can be inserted at any position and redirected at any point - so loops work inside eval(), you can include external files inside .sections and so on and so forth. This fixes a few issues (past, present and future) but the change broke a lot of plugins - hopefully I've repaired them now!

New plugin collection for scripting lets you script the assembler in any .NET-compatible language without needing to develop and install plugins. The documentation contains some samples in Visual Basic and C#.

The helper functions for retrieving arguments for directives and functions can now retrieve label references and unlimited optional arguments.

If there are any errors after pass one or pass two, the compiler cancels the build (rather than build everything twice).

Minor fixes on error reporting (command-line Brass.exe differentiates between warnings and errors, missing labels are reported as such rather than the default InvalidOperationException() text). The line spacing on the GUI builder has been reduced somewhat and you can Ctrl+C from it if need be.

I have added some (Sandcastle-generated) documentation on Brass itself. It's not really enough to get going, but it's a start.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Brass 3.0.0.0 Beta 6 wrote:Numerous fixes to Intel HEX writer (checksum calculation, page numbering, order of output); List file writers are run; Improved error detection on .page and .defpage directives.

.incscript syntax has changed; .scriptreference directive added.

Some TI application support along with a template and 2-page sample.

The Help Viewer now has an index with search-as-you-type functionality.
User avatar
driesguldolf
Extreme Poster
Posts: 395
Joined: Thu 17 May, 2007 4:49 pm
Location: $4080
Contact:

Post by driesguldolf »

Ha, found something :D (using brass 3.0.0.0 beta 6)

I thought this was the point of using modules:
Image

I've been having more troubles with modules, like labels defined in the global scope that aren't recognized inside modules (though they should) (plus, this doesn't happen with all labels :S), putting the labels inside a module block (with the same name) resolved that problem.


ps. sorry that I couldn't do more testing. School is absorbing waaaay more time then I want :(
Last edited by driesguldolf on Mon 26 Nov, 2007 3:35 pm, edited 1 time in total.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Thank you for the bug report and sample code. I've noticed some strange behaviour occasionally myself in this field, which has mostly been due to a bug in a plugin. This looks more like a bug in the LabelCollection class (which manages labels).
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Brass 3.0.0.0 Beta 7 wrote:Fixes to module/label access. This was a bit awkward to work on, so hopefully I didn't break anything else in the process. To aid this, there's a new label access keyword, global (to complement parent).

Removal of hard-coded strings from Brass.exe. They are now declared in resource files.

Conversion to C#3 and Visual Studio 2008. The project still targets .NET 2.0, however.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Brass 3.0.0.0 Beta 8 wrote:Corrected a $ and @ label resolution bug fixed.

Added a Dutch translation to Brass.exe by Timendus.

Added a feature to make sure that flow through the compiler source is the same on both passes. This is to try and protect against side-effects of not doing certain things in one pass, but doing them in another. Certain plugins may have been broken by this update.

Changed the way that reusable labels are checked, fixing cases where the assembler appears to hang when resolving the label name (in these cases it would in fact loop around past int.MaxValue and pick the first reusable label in the file).

Added a check for empty functions to the .function directive.

Changed string constants in core plugin collection to strings in a resource file, and added support for plugin documentation attributes to be extracted from resource files (specify the documentation attribute in the form resources://ResourceFileName/ResourceStringName). This can allow for translated documentation.
Apart from the dreadful English employed in the above, I've noticed that the calculator mode doesn't work properly (assignments are prohibited).
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Brass 3.0.0.0 Beta 9 wrote:Further label-related parsing bugs repaired.

A usage type is associated with labels, and can be set to Execution, Variable or Constant.

Added internal support for breakpoints. The breakpoint type can refer to execution, data read or data write breakpoints (as flags, so a single breakpoint could refer to a data read or a data write). Each breakpoint has an address and page associated with it, as well as a text description. Breakpoints do, unfortunately, rely on external debuggers recognising them.

A .breakpoint directive has been added, currently only with support for execution breakpoints at the current location.

Added an emukonpatch listing writer for the Sega Master System and Game Gear debugging emulator Emukon. It supports label exports, three types of variable (8-bit byte, 16-bit word and 32-bit dword) and execution breakpoints.

Released the source code.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Hm, I'm encountering more and more bugs caused by the flow through the source changing in the two passes (especially when calling user-defined functions), and for simplicity I'm considering changing the design to a single-pass assembler (this makes plugin development significantly simpler too).

The only real reason to have two passes is to support forward-referencing labels. To combat this, I think I'll add the capability for plugins to write constant output (as they currently do) or "dynamic" output, where the actual values (eg the target address in a jp * instruction) are inserted retrospectively.

This also could pave the way for relocatable binary libraries and the like, not to mention make the assembler faster. :)
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

relocatable binary libraries
Oooooooh :)

What did you have in mind? :)
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Timendus wrote:What did you have in mind? :)
Nothing in particular at the moment. :)

Currently, constant output data is transformed by any output modifiers (eg the "unsquisher" that converts output to ASCII text) and appended to a list recording its page, output location and program counter location so that the output writer plugin can dump it to disk in its own way.

What I intend on doing is having a similar list, but having the option to append expressions as well as constants so that at the end of the main assembling process the compiler can run through this list and perform those last-minute evaluations to substitute in the correct values that couldn't be determined before (forwards-referencing labels and the like).

Some directives will still need to be re-evaluated in this final pass, though, such as the directives to switch an output modifier on and off. These are in the minority, though.

By serialising this list of output data (static and dynamic) to disk somehow one could probably think up a suitable relocatable binary library format.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

I've started hacking together the new dynamic output data system.

Naturally, going from a true 2-pass assembler to a 1.5-pass assembler has resulted in a lot of code changes.

In most cases, this results in removing caching code or code designed to prevent code plugins from being run twice. In cases where output data were written, the worst that should theoretically happen is that you lose forwards-referencing.

The dynamic output is handled simply by a simple delegate:

Code: Select all

public delegate void DynamicDataGenerator(DynamicOutputData data);
DynamicOutputData is a simple class that inherits from the abstract OutputData class, containing a (currently empty) array of bytes (contrasting StaticOutputData that contains an array of bytes corresponding to what really needs to get output). It also has a reference to the delegate used to fill the array of bytes with the real values that cannot - at that point in the source - be calculated (forwards referencing and so on).

Code: Select all

compiler.WriteDynamicOutput(3, G => G.Data = new byte[] { 1, 2, 3 });
A crude example. :) The 3 is the size of the dynamic data (this is fixed, unfortunately) to be set aside. The second argument is the expression that is evaluated after the main compilation process to populate the array of bytes with the "dynamic" data, which can then be dumped to disk by an output writer.

You might have spotted one pit-fall; as code flows through the assembler certain state changes are made that can affect the dynamic data (for example, changing modules). Brass-provided state will be handled automatically. However, external plugins that modify data based on state (for example, the unsquisher can be switched on and off at will) will be able to attach an event handler to Brass to handle the addition of new dynamic data objects and embed their state within that object. Another event will be fired immediately before the dynamic data is asked to populate its internal array, which the external plugin can use to restore its state from the embedded state information in the dynamic output data object.

Frankly, a couple of weird plugins having to catch two events to maintain their state is much nicer than every plugin having to handle being called twice sanely as well as the potential synch problems that that occur depending on whether plugins get executed or not during the two passes.
Post Reply