From 2c37bced66a89451386f8ecc37de55d96394bcd7 Mon Sep 17 00:00:00 2001 From: Andrew Segavac Date: Sat, 25 Sep 2021 12:40:49 -0600 Subject: [PATCH] added interpereter support for traits --- examples/main.bl | 13 ++----- src/interpreter.rs | 84 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/examples/main.bl b/examples/main.bl index ce03029..ec2c4bb 100644 --- a/examples/main.bl +++ b/examples/main.bl @@ -28,11 +28,6 @@ fn unit_function() { let a: i64 = 4; } -fn main(): i64 { - add(4, subtract(5, 2)) -} - - fn returns_user(): User { return User{ id: 4, @@ -74,11 +69,9 @@ fn if_expression(): i64 { } fn main(): i64 { - if (false) { - add(4, 4) - } else { - 61 - } + let a = User{id: 4}; + let b = a.instance_method(); + b } type TestTrait trait { diff --git a/src/interpreter.rs b/src/interpreter.rs index 8c92b2c..2f1265f 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -29,11 +29,17 @@ pub struct StructValue { type BuiltinFunction = fn(Vec) -> Value; #[derive(Debug, Clone)] -pub enum Function { +pub enum FunctionRef { User(ast::Function), Builtin(BuiltinFunction), } +#[derive(Debug, Clone)] +pub struct Function { + pub partial: Vec, + pub ref_: FunctionRef, +} + #[derive(Debug, Clone)] pub enum Value { Numeric(NumericValue), @@ -89,7 +95,12 @@ impl Context { ast::ModuleItem::Function(function) => { ctx.environment.insert( function.declaration.name.name.value.to_string(), - NamedEntity::Variable(Value::Function(Function::User(function.clone()))), + NamedEntity::Variable(Value::Function( + Function{ + partial: vec!(), + ref_: FunctionRef::User(function.clone()), + } + )), ); } ast::ModuleItem::Impl(impl_) => { @@ -214,7 +225,12 @@ impl TreeWalkInterpreter { let mut ctx = Context::from_module(module); let main = match &ctx.environment["main"] { - NamedEntity::Variable(Value::Function(Function::User(func))) => func.clone(), + NamedEntity::Variable(Value::Function(func)) => { + match &func.ref_ { + FunctionRef::User(ref_) => ref_.clone(), + _ => panic!("main should be a user defined function"), + } + }, _ => panic!("main should be a user defined function"), }; @@ -362,15 +378,25 @@ impl TreeWalkInterpreter { argument_values.push(argument_value); } match &source { - Value::Function(Function::User(user_function)) => { - let mut fn_ctx = ctx.new_env(); - for (i, function_arg) in user_function.declaration.arguments.iter().enumerate() { - fn_ctx.set_variable(function_arg.name.name.value.to_string(), &argument_values[i].clone()); + Value::Function(function) => { + match &function.ref_ { + FunctionRef::User(user_function) => { + let mut fn_ctx = ctx.new_env(); + let mut i = 0; + for partial_arg in &function.partial { + fn_ctx.set_variable(user_function.declaration.arguments[i].name.name.value.to_string(), &partial_arg.clone()); + i = i + 1; + } + for argument_value in &argument_values { + fn_ctx.set_variable(user_function.declaration.arguments[i].name.name.value.to_string(), &argument_value.clone()); + } + return ExpressionResult::Value(self.with_function(&mut fn_ctx, user_function)); + } + FunctionRef::Builtin(builtin_function) => { + let all_values = function.partial.iter().map(|val| {val.clone()}).chain(argument_values.into_iter()).collect(); + return ExpressionResult::Value(builtin_function(all_values)); + } } - return ExpressionResult::Value(self.with_function(&mut fn_ctx, user_function)); - } - Value::Function(Function::Builtin(builtin_function)) => { - return ExpressionResult::Value(builtin_function(argument_values)); } _ => panic!("type error: function call source must be a function"), } @@ -414,7 +440,41 @@ impl TreeWalkInterpreter { match &source { Value::Struct(struct_) => { let s = struct_.lock().unwrap(); - return ExpressionResult::Value(s.fields[&struct_getter.attribute.name.value].clone()); + if s.fields.contains_key(&struct_getter.attribute.name.value) { + return ExpressionResult::Value(s.fields[&struct_getter.attribute.name.value].clone()); + } + for module_item in &ctx.current_module.items { + match module_item { + ast::ModuleItem::Impl(impl_) => { + if impl_.struct_name.name.value == s.source.name.name.value { + for method in &impl_.functions { + if method.declaration.name.name.value == struct_getter.attribute.name.value { + // if first type matches, partial apply self + if method.declaration.arguments.len() > 0 { + match &method.declaration.arguments[0].type_ { + ast::TypeUsage::Named(arg_named) => { + if arg_named.name.name.value == s.source.name.name.value { + return ExpressionResult::Value(Value::Function(Function{ + partial: vec!(source.clone()), + ref_: FunctionRef::User(method.clone()), + })); + } + } + _ => {}, + } + } + return ExpressionResult::Value(Value::Function(Function{ + partial: vec!(), + ref_: FunctionRef::User(method.clone()), + })); + } + } + } + } + _ => {} + } + } + panic!("TypeError: Method not found"); } _ => { panic!("TypeError: struct getter used with non-struct");