Yep, true, I've seen the same thing. I'm so used to it, that I correct in my head by instinct already, but it'd be great if this was fixed
I'm running into a small issue. The line number displayed when reporting an error is off by 1. In about every editor out there, the first line of the file is line 1, but if there's an error in the first line, Glass reports it as 0.
Yep, true, I've seen the same thing. I'm so used to it, that I correct in my head by instinct already, but it'd be great if this was fixed
Ah, well if there ever was an easy fix… I’ve uploaded a new development build.
Nice!! Thanks for the quick fix!
Hi Grauw, while working on parsing Glass syntax on my optimizer, I think I might have found some corner case in the behavior of Macros in Glass (or maybe just a misunderstanding from my part haha). The documentation specifies that when you define a macro, "the contents are assembled on address 0, effectively turning the inner symbols into offsets", however, I could not understand how did that happen since the symbol values might depend on the parameters of the Macro. So, I did some tests. For example, if I define a macro like this:
mymacro: MACRO ?parameter REPT ?parameter db 0 ENDM local_label: db 0 ENDM
local_label, really depends on the value of ?parameter. Glass assigns "local_label" the value 0, but it really should maybe give a compilation error or warning, as local_label cannot really be determined. Right? When my optimizer is configured to use "Glass" idiom, I thought I would just compile the content of macros assuming all parameters have a numeric value of "0", but that does not sound right. What is the logic that Glass follows? Anyway, just making sure I get it right in my parser
Hey santiontanon, this is indeed the case when you dereference labels in the macro definition. It uses either the default if specified, or else a 0. If it can’t compile with 0’s it silently fails and the scope will be empty.
In the future I want to add the ability to explicitly specify the parameter value in expressions (e.g. ld hl,(mymacro 20).local_label
), however that is not supported yet. It could indeed also be interesting if it didn’t actually pass zeroes, rather it passed an error value and as long as it’s not evaluated it can yield the values. However for that I need to have more lazy evaluation (also something I’m working on). The feature is originally meant to create structs, and it was useful to allow parameterisation, so I opted for the automatic 0’s at the time as something that was feasible then. But it’s not perfect yet I agree.
Okay! Makes sense! I'll implement it that way then! I just wanted to make sure I got the same semantics
Hi Grauw, while continuing my work on MDL, I've detected some issues in Glass that just wanted to bring to your attention. Maybe it is all intended behavior, but just checking. Consider the following code:
val1: equ (128 - 8) val2: equ 128 - 8 ld bc,val1 ; this is compiled as ld bc,(128-8) ld bc,val2 ; this is compiled as ld bc,128-8 ;ld (hl),val1 ; this does not compile ld (hl),val2 ; this is compiled as ld (hl),128-8 ;end: ; Glass does not like "end" as a label, so this does not compile ; jr end
I can understand why does this happen. But isn't it weird that if you define a val1 as "(128-8"), when used in "ld bc,val1" it is taken as an indirection? I know it has parenthesis around, but this can be quite confusing as the parenthesis does not explicitly appear in the instruction. I found this issue because sjasm interprets all of the statements above ignoring the parenthesis in val1.
Also, I am confused about why can't we use "end" as a label, since "end" is not any of the reserved keywords in Glass (like "endm" or "ends"), right?
Anyway, just reporting in case any of these was not intended
Hi santiontanon,
“It’s a feature, not a bug.” The Glass assembler evaluates symbols through (more or less) substitution, so what you see is what you get. If it did not do this, it would be impossible to pass indirect references, e.g. (hl) when passing a register. Unfortunately it is an ideosyncracy of the standard Z80 language that parentheses have meaning, it is a pain point. I don’t know a better way to handle this without taking away functionality or deviating from standard syntax.
The simple solution however is to not add superfluous parentheses around your equation. I myself would never do that in the first place , but it’s been reported before.
The end label I will look in to. Glass does use END internally to denote the end of a file, and you can also use it to end processing of a file prematurely (though I would not recommend and did not document). However I think it’s not good when “end” does not work as a label, so I need to change it.
I remember other assemblers that don't like end as a label (If I am not mistaken, chaos assembler was one of them). Infact I used to name last label as "theend:" or "the_end:"
Re: "end": Oh, I see, so, it's an internally used label. Makes sense! I think either is fine, either allowing it or mentioning it in the doc would be fine I was just surprised! It came up because one of the codebases I use for testing is in sjasm, and "end" is a valid label. So, when I translate to Glass and try to compile, that label fails. But I can also define some internal list of "unsafe label names", and add some prefix to those before writing output. So, not that important
Re: parenthesis: Yes, the "parenthesis for indirections" is indeed a recurring pain point in z80 syntax. But in this case, what is surprising is that the parenthesis does not appear directly in the instruction line. So, it's "hidden", which is confusing. I think Glass maybe evaluates expressions lazily, and thus the parenthesis is there by the time you parse the instruction, while sjasm/asMSX and others evaluate expressions in an eager way, and thus the parenthesis is not there anymore when it comes time to parse the instruction. My parser evaluates lazily, but determines the instruction type by looking at the expression written directly in the CPU instruction line, before resolving any symbols. I like this solution, as it seems to me the most intuitive. But of course, there is no right or wrong answer here, as it all depends on the convention you decide to follow for the semantics of "equ" (whether it's a "value" assignment, or if it is a "raw string" assignment, or when is its value evaluated). So, I think either solution is fine. Maybe it'd be worth adding a line or two in the documentation about the order in which things are evaluated, etc. so this is clear though
I was just reporting it as compiling the small asm code snippet above with Glass and sjasm both compilers give different outputs, and surprised me!
I think while working on MDL I am finding all kinds of corner cases in different assemblers though hahaha. For example, there are a few places where the sjasm syntax is ambiguous (e.g., the reusable label reference "1b" could be interpreted as a reusable label or as "1" in binary, and which one does the compiler pick is arbitrary ), and a few where, for some reason, it "swallows" incorrect syntax without complaining (I've found instances of this in both sjasm and asMSX).