fn check_statement(&mut self, s: &mut Statement) -> Result<(), String> {
        match *s {
            // Block
            Statement::Block(ref mut v) => {
                self.push_scope();
                for s in v.iter_mut() {
                    match self.check_statement(s) {
                        Err(msg) => { self.pop_scope(); return Err(msg); },
                        Ok(_) => {}
                    }
                }
                self.pop_scope();
                Ok(())
            },

            // Declaration Statement
            Statement::Declare(ref mut t, ref ident, ref expr) => {
                let derived = try!(self.derive_type(expr));

                // If the given type is unknown, then change it to the derived type
                if *t == Type::Unknown {
                    *t = derived.clone();
                }

                // If the LHS matches the RHS, we're okay
                if *t == derived {
                    self.variables[self.depth - 1].insert(ident.clone(), t.clone());
                    Ok(())
                } else {
                    Err(format!("value being used to initialise '{}' does not match its declared type (expected: {:?}, actual: {:?})", ident, t, derived))
                }
            },

            // Assignment Statement
            Statement::Assign(ref ident, ref expr) => {
                let derived = try!(self.derive_type(expr));

                // Look up the variable in the current scope
                // TODO: Check upper scopes and function parameters
                match self.variables[self.depth - 1].get(ident) {
                    // If the variable exists, check that its type matches the RHS
                    Some(ref t) => if **t != derived {
                        Err(format!("cannot assign rvalue to lvalue of a different type (expected: {:?}, actual: {:?})", t, derived))
                    } else {
                        Ok(())
                    },
                    None => Err(format!("use of undeclared variable '{}'", ident))
                }
            },

            // Return Statement
            Statement::Return(ref expr) => {
                try!(self.derive_type(expr));
                Ok(())
            }

            // Print builtin
            Statement::Print(ref expr) => {
                try!(self.derive_type(expr));
                Ok(())
            }
        }
    }
/// Given a statement, check that it is semantically valid
Given a statement, check that it is semantically valid
Given a statement check that it is semantically valid
fn check_statement(&mut self, s: &mut Statement) -> Result<(), String> {
        match *s {
            // Block
            Statement::Block(ref mut v) => {
                self.push_scope();
                for s in v.iter_mut() {
                    match self.check_statement(s) {
                        Err(msg) => { self.pop_scope(); return Err(msg); },
                        Ok(_) => {}
                    }
                }
                self.pop_scope();
                Ok(())
            },
            // Declaration Statement
            Statement::Declare(ref mut t, ref ident, ref expr) => {
                let derived = try!(self.derive_type(expr));
                // If the given type is unknown, then change it to the derived type
                if *t == Type::Unknown {
                    *t = derived.clone();
                }
                // If the LHS matches the RHS, we're okay
                if *t == derived {
                    self.variables[self.depth - 1].insert(ident.clone(), t.clone());
                    Ok(())
                } else {
                    Err(format!("value being used to initialise '{}' does not match its declared type (expected: {:?}, actual: {:?})", ident, t, derived))
                }
            },
            // Assignment Statement
            Statement::Assign(ref ident, ref expr) => {
                let derived = try!(self.derive_type(expr));
                // Look up the variable in the current scope
                // TODO: Check upper scopes and function parameters
                match self.variables[self.depth - 1].get(ident) {
                    // If the variable exists, check that its type matches the RHS
                    Some(ref t) => if **t != derived {
                        Err(format!("cannot assign rvalue to lvalue of a different type (expected: {:?}, actual: {:?})", t, derived))
                    } else {
                        Ok(())
                    },
                    None => Err(format!("use of undeclared variable '{}'", ident))
                }
            },
            // Return Statement
            Statement::Return(ref expr) => {
                try!(self.derive_type(expr));
                Ok(())
            }
            // Print builtin
            Statement::Print(ref expr) => {
                try!(self.derive_type(expr));
                Ok(())
            }
        }
    }
fn check_statement ( & mut self , s : & mut Statement ) -> Result < ( ) , String > { match * s { // Block Statement :: Block ( ref mut v ) => { self . push_scope ( ) ; for s in v . iter_mut ( ) { match self . check_statement ( s ) { Err ( msg ) => { self . pop_scope ( ) ; return Err ( msg ) ; } , Ok ( _ ) => { } } } self . pop_scope ( ) ; Ok ( ( ) ) } , // Declaration Statement Statement :: Declare ( ref mut t , ref ident , ref expr ) => { let derived = try ! ( self derive_type ( expr ) ) ; // If the given type is unknown, then change it to the derived type if * t == Type :: Unknown { * t = derived . clone ( ) ; } // If the LHS matches the RHS, we're okay if * t == derived { self . variables [ self . depth - 1 ] . insert ( ident . clone ( ) , t . clone ( ) ) ; Ok ( ( ) ) } else { Err ( format ! ( " " ident t derived ) ) } } , // Assignment Statement Statement :: Assign ( ref ident , ref expr ) => { let derived = try ! ( self derive_type ( expr ) ) ; // Look up the variable in the current scope // TODO: Check upper scopes and function parameters match self . variables [ self . depth - 1 ] . get ( ident ) { // If the variable exists, check that its type matches the RHS Some ( ref t ) => if * * t != derived { Err ( format ! ( " " t derived ) ) } else { Ok ( ( ) ) } , None => Err ( format ! ( " " ident ) ) } } , // Return Statement Statement :: Return ( ref expr ) => { try ! ( self derive_type ( expr ) ) ; Ok ( ( ) ) } // Print builtin Statement :: Print ( ref expr ) => { try ! ( self derive_type ( expr ) ) ; Ok ( ( ) ) } } }
Given a statement, check that it is semantically valid
Given a statement check that it is semantically valid
&mut self
s
&mut Statement
&mut self
s
&mut Statement