Brass 3.0.0.0 Beta 13
-
- Calc King
- Posts: 1513
- Joined: Sat 05 Aug, 2006 7:22 am
- driesguldolf
- Extreme Poster
- Posts: 395
- Joined: Thu 17 May, 2007 4:49 pm
- Location: $4080
- Contact:
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:
I may not be fully qualified, but I do know what a stylesheet is
I haven't got my hands dirty on macros and functions yet, so here I go
Where can I find a list of all build in functions? EDIT: ofcourse plugin site... I need to look better...
if a name is used double, show a warning, and use the one with the function highest on this list:
- Instructions
- Functions
- Macros
- Labels
I may not be fully qualified, but I do know what a stylesheet is
I haven't got my hands dirty on macros and functions yet, so here I go
Where can I find a list of all build in functions? EDIT: ofcourse plugin site... I need to look better...
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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)).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
The way the compiler works is that it starts with a string of tokens, like this:
Code: Select all
label = 1 xor a
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.
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).
I was being silly, it's a bad error message due to some lazy programming on my behalf.Yes I suspected some unprocessed exception, but I was thinking from the pov of someone who never heard of .NET
I may not be fully qualified, but I do know what a stylesheet is
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.Where can I find a list of all build in functions?
Note that there have been several architectural changes since a lot of those have been written, so they might not all work properly.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
- driesguldolf
- Extreme Poster
- Posts: 395
- Joined: Thu 17 May, 2007 4:49 pm
- Location: $4080
- Contact:
Ha, found something (using brass 3.0.0.0 beta 6)
I thought this was the point of using modules:
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
I thought this was the point of using modules:
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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Apart from the dreadful English employed in the above, I've noticed that the calculator mode doesn't work properly (assignments are prohibited).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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
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.
Ooooooohrelocatable binary libraries
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
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Nothing in particular at the moment.Timendus wrote:What did you have in mind?
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.
- benryves
- Maxcoderz Staff
- Posts: 3087
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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:
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).
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.
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);
Code: Select all
compiler.WriteDynamicOutput(3, G => G.Data = new byte[] { 1, 2, 3 });
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.