From 1daf23b129f0dc28f827fc8f5346eb4581abec4f Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Tue, 25 Jan 2022 01:35:27 -0800 Subject: [PATCH] Support methods sort of This is broken b/c not type aware, but will do for now --- schala-lang/src/reduced_ir/mod.rs | 35 ++++++++++++++++++++++---- schala-lang/src/reduced_ir/test.rs | 19 +++++++++++++- schala-lang/src/tree_walk_eval/test.rs | 17 +++++++++++++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/schala-lang/src/reduced_ir/mod.rs b/schala-lang/src/reduced_ir/mod.rs index ededbd5..7d6b078 100644 --- a/schala-lang/src/reduced_ir/mod.rs +++ b/schala-lang/src/reduced_ir/mod.rs @@ -71,10 +71,23 @@ impl<'a, 'b> Reducer<'a, 'b> { //TODO expressions can in principle contain definitions, but I won't worry //about it now } - ast::StatementKind::Declaration(decl) => - if let ast::Declaration::FuncDecl(_, statements) = decl { + ast::StatementKind::Declaration(decl) => match decl { + ast::Declaration::FuncDecl(_, statements) => { self.insert_function_definition(item_id, statements); - }, + } + ast::Declaration::Impl { type_name: _, interface_name: _, block } => + for item in block { + if let ast::Statement { + id: item_id, + kind: ast::Declaration::FuncDecl(_, statements), + .. + } = item + { + self.insert_function_definition(item_id, statements); + } + }, + _ => (), + }, // Imports should have already been processed by the symbol table and are irrelevant // for this representation. ast::StatementKind::Import(..) => (), @@ -124,6 +137,18 @@ impl<'a, 'b> Reducer<'a, 'b> { self.functions.insert(symbol.def_id(), function_def); } + //TODO this needs to be type-aware to work correctly + fn lookup_method(&mut self, name: &str) -> Option { + for (def_id, function) in self.functions.iter() { + let symbol = self.symbol_table.lookup_symbol_by_def(def_id)?; + println!("Def Id: {} symbol: {:?}", def_id, symbol); + if symbol.local_name() == name { + return Some(*def_id); + } + } + None + } + fn expression(&mut self, expr: &ast::Expression) -> Expression { use crate::ast::ExpressionKind::*; @@ -142,8 +167,8 @@ impl<'a, 'b> Reducer<'a, 'b> { let args = arguments.iter().map(|arg| self.invocation_argument(arg)).collect(); //TODO need to have full type availability at this point to do this method lookup //correctly - if let Expression::Access { name: _, expr } = f { - let def_id = unimplemented!(); + if let Expression::Access { name, expr } = f { + let def_id = self.lookup_method(&name).unwrap(); let method = Expression::Lookup(Lookup::Function(def_id)); Expression::CallMethod { f: Box::new(method), args, self_expr: expr } } else { diff --git a/schala-lang/src/reduced_ir/test.rs b/schala-lang/src/reduced_ir/test.rs index 55eb4a7..ca12230 100644 --- a/schala-lang/src/reduced_ir/test.rs +++ b/schala-lang/src/reduced_ir/test.rs @@ -40,5 +40,22 @@ fn test_ir() { let reduced = build_ir(src); assert_eq!(reduced.functions.len(), 3); - //assert!(1 == 2); +} + +#[test] +fn test_methods() { + let src = r#" +type Thing = Thing +impl Thing { + fn a_method() { + 20 + } + +} + +let a = Thing +4 + a.a_method() + "#; + let reduced = build_ir(src); + assert_eq!(reduced.functions.len(), 1); } diff --git a/schala-lang/src/tree_walk_eval/test.rs b/schala-lang/src/tree_walk_eval/test.rs index ec155d1..94475af 100644 --- a/schala-lang/src/tree_walk_eval/test.rs +++ b/schala-lang/src/tree_walk_eval/test.rs @@ -545,3 +545,20 @@ fn foo() { return 2 } "(7, 9)", ); } + +#[test] +fn eval_method() { + let src = r#" +type Thing = Thing +impl Thing { + fn a_method() { + 20 + } + +} + +let a = Thing::Thing +4 + a.a_method() + "#; + eval_assert(src, "24"); +}