Introduce true and false conditions #21

Manually merged
MightyPork merged 2 commits from User_4574/crsn:master into master 4 years ago
  1. 3
      README.md
  2. 10
      crsn/src/asm/instr/cond.rs
  3. 4
      crsn/src/asm/instr/flatten.rs
  4. 2
      crsn/src/runtime/frame/status.rs
  5. 17
      examples/test_cond.csn

@ -98,6 +98,8 @@ These keywords (among others) are used in conditional branches to specify flag t
- `nem`, `nempty` … Not empty - `nem`, `nempty` … Not empty
- `eof` … EOF - `eof` … EOF
- `neof` … Not EOF - `neof` … Not EOF
- `true`, `always`, `else` … Always true
- `false`, `never` … Always false
# Syntax # Syntax
@ -207,6 +209,7 @@ Conditonal branches are written like this:
then only one branch is taken - there is no fall-through. then only one branch is taken - there is no fall-through.
- The definition order is preserved, i.e. if the `inval` flag is to be checked, it should be done - The definition order is preserved, i.e. if the `inval` flag is to be checked, it should be done
before checking e.g. `nz`, which is, incidentally, true by default, because most flags are cleared by instructions that affects flags. before checking e.g. `nz`, which is, incidentally, true by default, because most flags are cleared by instructions that affects flags.
- `else` can be used as a final choice of branch that will always be taken.
## Routines ## Routines

@ -106,6 +106,10 @@ pub enum Cond {
Eof, Eof,
/// Not empty /// Not empty
NotEof, NotEof,
// Always true, for eg. (else? ...)
True,
/// Always false
False,
} }
pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> { pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
@ -134,6 +138,7 @@ pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
"neof" => Cond::NotEof, "neof" => Cond::NotEof,
"ov" => Cond::Overflow, "ov" => Cond::Overflow,
"nov" => Cond::NotOverflow, "nov" => Cond::NotOverflow,
"else" => Cond::True,
_ => { _ => {
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos.clone())); return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos.clone()));
} }
@ -174,6 +179,8 @@ impl Display for Cond {
Cond::Valid => "valid", Cond::Valid => "valid",
Cond::Eof => "eof", Cond::Eof => "eof",
Cond::NotEof => "neof", Cond::NotEof => "neof",
Cond::True => "else",
Cond::False => "never",
}) })
} }
} }
@ -214,6 +221,9 @@ impl Not for Cond {
Cond::NotEof => Cond::Eof, Cond::NotEof => Cond::Eof,
Cond::Eof => Cond::NotEof, Cond::Eof => Cond::NotEof,
Cond::True => Cond::False,
Cond::False => Cond::True,
} }
} }
} }

@ -49,6 +49,10 @@ impl Flatten for InstrWithBranches {
return Err(CrsnError::Asm(AsmError::ConditionalAlreadyUsed(cond), branch.pos())); return Err(CrsnError::Asm(AsmError::ConditionalAlreadyUsed(cond), branch.pos()));
} }
if cnt != branch_count - 1 && cond == Cond::True {
warn!("\"Else\" conditional used in non-final branch at {}:{}", branch.pos().line, branch.pos().column);
}
let next_lbl = if cnt == branch_count - 1 { let next_lbl = if cnt == branch_count - 1 {
end_lbl.clone() end_lbl.clone()
} else { } else {

@ -115,6 +115,8 @@ impl StatusFlags {
Cond::NotEmpty => !self.empty, Cond::NotEmpty => !self.empty,
Cond::Eof => self.eof, Cond::Eof => self.eof,
Cond::NotEof => !self.eof, Cond::NotEof => !self.eof,
Cond::True => true,
Cond::False => false,
} }
} }

@ -0,0 +1,17 @@
(
(ld r8 0)
(ld r0 1
(else? (add r8 1))
)
(sub r0 1
(pos? (fault))
(else? (add r8 1))
)
(cmp r8 2
(ne? (fault))
)
)
Loading…
Cancel
Save