Support methods sort of

This is broken b/c not type aware, but will do for now
This commit is contained in:
Greg Shuflin 2022-01-25 01:35:27 -08:00
parent c1b5fa392a
commit 1daf23b129
3 changed files with 65 additions and 6 deletions

View File

@ -71,9 +71,22 @@ impl<'a, 'b> Reducer<'a, 'b> {
//TODO expressions can in principle contain definitions, but I won't worry //TODO expressions can in principle contain definitions, but I won't worry
//about it now //about it now
} }
ast::StatementKind::Declaration(decl) => ast::StatementKind::Declaration(decl) => match decl {
if let ast::Declaration::FuncDecl(_, statements) = decl { ast::Declaration::FuncDecl(_, statements) => {
self.insert_function_definition(item_id, 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 // Imports should have already been processed by the symbol table and are irrelevant
// for this representation. // for this representation.
@ -124,6 +137,18 @@ impl<'a, 'b> Reducer<'a, 'b> {
self.functions.insert(symbol.def_id(), function_def); 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<DefId> {
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 { fn expression(&mut self, expr: &ast::Expression) -> Expression {
use crate::ast::ExpressionKind::*; 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(); 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 //TODO need to have full type availability at this point to do this method lookup
//correctly //correctly
if let Expression::Access { name: _, expr } = f { if let Expression::Access { name, expr } = f {
let def_id = unimplemented!(); let def_id = self.lookup_method(&name).unwrap();
let method = Expression::Lookup(Lookup::Function(def_id)); let method = Expression::Lookup(Lookup::Function(def_id));
Expression::CallMethod { f: Box::new(method), args, self_expr: expr } Expression::CallMethod { f: Box::new(method), args, self_expr: expr }
} else { } else {

View File

@ -40,5 +40,22 @@ fn test_ir() {
let reduced = build_ir(src); let reduced = build_ir(src);
assert_eq!(reduced.functions.len(), 3); 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);
} }

View File

@ -545,3 +545,20 @@ fn foo() { return 2 }
"(7, 9)", "(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");
}