hlorenzi / customasm

💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/
Apache License 2.0
704 stars 55 forks source link

No match for instruction with negative numbers #186

Closed flaviojs closed 9 months ago

flaviojs commented 10 months ago

Version: v0.13.4

Rule matching fails when I use negative numbers. The argument type is i14 so negative numbers should be ok.

Workaround: use a function to negate a positive value

Example

#ruledef ppc32 { ; PowerPC 32-bit
    ; Branch Conditional
    bcx {BO: u5} {BI: u5} {BD: i14} {AA: u1} {LK: u1} => 0b010000 @ BO @ BI @ BD @ AA @ LK
    bc {BO} {BI} {target_addr} => asm { bcx {BO} {BI} {target_addr} 0 0 }
    bca {BO} {BI} {target_addr} => asm { bcx {BO} {BI} {target_addr} 1 0 }
    blc {BO} {BI} {target_addr} => asm { bcx {BO} {BI} {target_addr} 0 1 }
    blca {BO} {BI} {target_addr} => asm { bcx {BO} {BI} {target_addr} 1 1 }
}

; workaround to get negative values
#fn minus(value) => 0 - value

#bankdef test {
    #bits 32
    #outp 0
}

#bank test
    bc 4 2 5
    bc 4 2 minus(5)
    ;bc 4 2 -5 ; error: no match found for instruction
flaviojs commented 10 months ago
; workaround 2 -just use a function
#fn value(x) => x

    bc 4 2 value(-5)
flaviojs commented 10 months ago
; workaround 3 - add commas
#ruledef {
    bcx {BO: u5}, {BI: u5}, {BD: i14}, {AA: u1}, {LK: u1} => 0b010000 @ BO @ BI @ BD @ AA @ LK
    bc {BO}, {BI}, {target_addr} => asm { bcx {BO}, {BI}, {target_addr}, 0, 0 }
}

    bc 4, 2, -5

Conclusion: a single space is not enough to separate instruction arguments?

chrisgbk commented 10 months ago

I'm going to guess that 2 -5 is being simplified to -3, as it looks like a mathematical expression instead of separate arguments.

flaviojs commented 10 months ago

That makes sense, thanks. Then the real problem is not having a helpful error message.

Anything that works with a "missing argument" example like:

    bc 4, 2

Ideally it would show the closest match and what part failed to match.

chrisgbk commented 10 months ago

I checked and verified for sure, and my guess was correct, adding a syntax with one less argument gets a match, and that match was -3 when output.

This issue can additionally be worked around by specifying all negative numbers -x as 0-x or x*-1. Notably, (-x) by itself does not work, as that tries to call a function y(-x) which is uncallable.

hlorenzi commented 10 months ago

chrisgbk is right in that 2 -5 just looks like a single expression to the parser. Every time there's an expression parameter, it greedily tries to consume an expression. Positive numbers like 2 5 should work, though, since that's not a valid expression and will be broken apart.

You're right that a single space isn't enough. The suggestion here is always to introduce some separator token between parameters, like a comma or anything else that would be invalid in an expression, so there's no ambiguity.

I'd also love to have the assembler detail what issues it encountered during instruction matching, so that you know exactly what went wrong! But I just couldn't yet think of how to implement that feature in the current architecture, and what message format would be the most helpful. If we're not careful, I imagine this explanation could become just as cryptic and confusing as the problem itself.

(And perhaps we should make expressions such as the uncallable 2 (-5) obviously wrong to the parser, so that it's able to break it apart into two parameters. But that might prove to be a bit of a headache, since we'd be trying to fix a semantics error in the syntax parser.)

flaviojs commented 10 months ago

Ok, document that a non-space separator is recommended between arguments. A negative number example can be used to show what could go wrong. The code does not contain docs and the wiki is not editable by random people so I cannot help there.

Normally I wouldn't mind trying to implement an appropriate error message, but I cannot use cargo fmt in this project. I don't want to handle non-automatic formatting so I'm out.