Interpreter - Fixed class declaration handling

This commit is contained in:
Emmanuel BENOîT 2023-01-14 13:34:18 +01:00
parent 71a58c12a2
commit fb7f2f16fa

View file

@ -2,8 +2,8 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::{ use crate::{
ast::{ ast::{
ClassDecl, ClassMemberDecl, ExprNode, FunDecl, GetExpr, ProgramNode, SetExpr, StmtNode, ClassDecl, ClassMemberDecl, ClassMemberKind, ExprNode, FunDecl, GetExpr, ProgramNode,
VariableExpr, SetExpr, StmtNode, VariableExpr,
}, },
errors::{ErrorKind, SloxError, SloxResult}, errors::{ErrorKind, SloxError, SloxResult},
resolver::ResolvedVariables, resolver::ResolvedVariables,
@ -197,25 +197,26 @@ impl StmtNode {
Ok(InterpreterFlowControl::default()) Ok(InterpreterFlowControl::default())
} }
/// Extract methods from a class declaration /// Extract members from a class declaration, generating a map of
fn extract_methods<F>( /// functions.
fn extract_members<F>(
&self, &self,
es: &mut InterpreterState, es: &mut InterpreterState,
decl: &ClassDecl, decl: &ClassDecl,
filter: F, filter: F,
) -> HashMap<String, Function> ) -> HashMap<String, Function>
where where
F: FnMut(&ClassMemberDecl) -> Option<&FunDecl>, F: FnMut(&ClassMemberDecl) -> Option<(&FunDecl, &[Token])>,
{ {
decl.members decl.members
.iter() .iter()
.filter_map(filter) .filter_map(filter)
.map(|fdecl| { .map(|(fdecl, params)| {
( (
fdecl.name.lexeme.clone(), fdecl.name.lexeme.clone(),
Function::new( Function::new(
Some(&fdecl.name), Some(&fdecl.name),
&fdecl.params, &params,
&fdecl.body, &fdecl.body,
es.environment.clone(), es.environment.clone(),
fdecl.name.lexeme == "init", fdecl.name.lexeme == "init",
@ -228,12 +229,18 @@ impl StmtNode {
/// Handle a class declaration /// Handle a class declaration
fn on_class_decl(&self, es: &mut InterpreterState, decl: &ClassDecl) -> InterpreterResult { fn on_class_decl(&self, es: &mut InterpreterState, decl: &ClassDecl) -> InterpreterResult {
es.environment.borrow_mut().define(&decl.name, None)?; es.environment.borrow_mut().define(&decl.name, None)?;
let methods = self.extract_methods(es, decl, |member| match member { let methods =
ClassMemberDecl::Method(method) => Some(method), self.extract_members(es, decl, |member| match (&member.kind, member.is_static) {
(ClassMemberKind::Method, false) => {
Some((&member.fun_decl, &member.fun_decl.params))
}
_ => None, _ => None,
}); });
let static_methods = self.extract_methods(es, decl, |member| match member { let static_methods =
ClassMemberDecl::StaticMethod(method) => Some(method), self.extract_members(es, decl, |member| match (&member.kind, member.is_static) {
(ClassMemberKind::Method, true) => {
Some((&member.fun_decl, &member.fun_decl.params))
}
_ => None, _ => None,
}); });
let class = Class::new(decl.name.lexeme.clone(), methods, static_methods); let class = Class::new(decl.name.lexeme.clone(), methods, static_methods);