@ -3,7 +3,7 @@ use std::convert::TryFrom;
use sexp ::{ Atom , Sexp , SourcePosition } ;
use crate ::asm ::data ::{ DataDisp , Rd , RdData , reg , Wr , WrData , RdWr } ;
use crate ::asm ::data ::{ DataDisp , Rd , RdData , reg , Wr , WrData , RdWr , Register } ;
use crate ::asm ::data ::literal ::{ ConstantName , Label , RegisterAlias , Value } ;
use crate ::asm ::error ::CrsnError ;
use crate ::asm ::parse ::{ ParserContext , parse_instructions } ;
@ -75,6 +75,7 @@ pub fn parse_label_str(name: &str, pos: &SourcePosition) -> Result<Label, CrsnEr
pub fn parse_data_disp ( tok : Sexp , pcx : & ParserContext ) -> Result < DataDisp , CrsnError > {
// trace!("parse data: {:?}", tok);
match tok {
// immediates are okay in const eval - no tests needed
Sexp ::Atom ( Atom ::I ( val ) , _pos ) = > {
Ok ( DataDisp ::Immediate ( unsafe { std ::mem ::transmute ( val ) } ) )
}
@ -92,10 +93,12 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
}
Sexp ::List ( list , pos ) = > {
if let Some ( Sexp ::Atom ( Atom ::S ( s ) , s_pos ) ) = list . first ( ) {
// Const eval
let parsing_expr = pcx . state . borrow ( ) . parsing_expr ;
if ! s . starts_with ( '=' ) & & ! parsing_expr {
return Err ( CrsnError ::Parse ( format! ( "Invalid syntax, did you mean \"={}\"?" , s ) . into ( ) , s_pos . clone ( ) ) ) ;
return Err ( CrsnError ::Parse ( format! ( "Invalid syntax, did you mean \"={}\" (a compile-time expression) ?" , s ) . into ( ) , s_pos . clone ( ) ) ) ;
}
// start expr parsing mode
@ -116,6 +119,10 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
let op = expr_ops . remove ( 0 ) ;
if ! op . is_compile_time_evaluable ( ) {
return Err ( CrsnError ::Parse ( format! ( "Instruction {} cannot be used in an expression!" , op . to_sexp ( ) ) . into ( ) , pos . clone ( ) ) ) ;
}
let mut state_mut = pcx . state . borrow_mut ( ) ;
state_mut . const_eval . clear_all ( ) ;
@ -144,12 +151,16 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
}
/// Parse data disp from a string token (a &str is used so the string can be preprocessed)
pub fn parse_data_disp_from_str ( s : & str , pos : & SourcePosition , pcx : & ParserContext ) -> Result < DataDisp , CrsnError > {
fn parse_data_disp_from_str ( s : & str , pos : & SourcePosition , pcx : & ParserContext ) -> Result < DataDisp , CrsnError > {
if s = = "_" {
return Ok ( DataDisp ::Discard ) ;
}
if let Some ( reference ) = s . strip_prefix ( '@' ) {
if pcx . state . borrow ( ) . parsing_expr {
return Err ( CrsnError ::Parse ( "Object handles cannot be used in expressions!" . into ( ) , pos . clone ( ) ) ) ;
}
/* extension constants (pre-defined handles) */
for p in pcx . parsers {
if let Some ( val ) = p . get_constant_value ( reference ) {
@ -188,7 +199,7 @@ pub fn parse_data_disp_from_str(s: &str, pos: &SourcePosition, pcx: &ParserConte
return Ok ( DataDisp ::Immediate ( * val ) ) ;
}
/* register aliases */
/* register aliases - no need to check for const_eval, the aliases could never be defined */
if let Some ( val ) = pstate . reg_aliases . get ( s ) {
return Ok ( DataDisp ::Register ( * val ) ) ;
} else if let Some ( val ) = pstate . global_reg_aliases . get ( s ) {
@ -215,6 +226,14 @@ pub fn parse_data_disp_from_str(s: &str, pos: &SourcePosition, pcx: &ParserConte
}
}
if pcx . state . borrow ( ) . parsing_expr {
if s = = "=result" {
return Ok ( DataDisp ::Register ( Register ::Gen ( 0 ) ) ) ;
} else {
return Err ( CrsnError ::Parse ( "Registers cannot be used in expressions!" . into ( ) , pos . clone ( ) ) ) ;
}
}
/* register */
let reg = reg ::parse_reg ( & s , & pos ) ? ;
@ -231,39 +250,13 @@ pub fn parse_data_disp_from_str(s: &str, pos: &SourcePosition, pcx: &ParserConte
/// Parse immediate value
pub fn parse_value ( tok : Sexp , pcx : & ParserContext ) -> Result < ( Value , SourcePosition ) , CrsnError > {
match tok {
Sexp ::Atom ( Atom ::I ( val ) , pos ) = > {
Ok ( ( unsafe { std ::mem ::transmute ( val ) } , pos ) )
}
Sexp ::Atom ( Atom ::U ( val ) , pos ) = > {
Ok ( ( val , pos ) )
}
Sexp ::Atom ( Atom ::C ( val ) , pos ) = > {
Ok ( ( val as u64 , pos ) )
}
Sexp ::Atom ( Atom ::QS ( _ ) , pos ) = > {
Err ( CrsnError ::Parse ( "quoted string not expected here" . into ( ) , pos ) )
}
Sexp ::Atom ( Atom ::F ( val ) , pos ) = > {
Ok ( ( unsafe { std ::mem ::transmute ( val ) } , pos ) )
}
Sexp ::Atom ( Atom ::S ( s ) , pos ) = > {
let pstate = pcx . state . borrow ( ) ;
if let Some ( val ) = pstate . constants . get ( & s ) {
return Ok ( ( * val , pos ) ) ;
}
/* extension constants */
for p in pcx . parsers {
if let Some ( val ) = p . get_constant_value ( & s ) {
return Ok ( ( val , pos ) ) ;
}
}
let pos = tok . pos ( ) . clone ( ) ;
let parsed = parse_rd ( tok , pcx ) ? ;
Err ( CrsnError ::Parse ( format! ( "unknown constant: {}" , s ) . into ( ) , pos ) )
}
Sexp ::List ( _ , pos ) = > {
Err ( CrsnError ::Parse ( "expected a value" . into ( ) , pos ) )
match parsed {
Rd ( RdData ::Immediate ( value ) ) = > Ok ( ( value , pos ) ) ,
_ = > {
Err ( CrsnError ::Parse ( "expected an immediate value" . into ( ) , pos ) )
}
}
}