added interpereter support for traits

This commit is contained in:
Andrew Segavac
2021-09-25 12:40:49 -06:00
parent 44df5f1980
commit 2c37bced66
2 changed files with 75 additions and 22 deletions

View File

@@ -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 {

View File

@@ -29,11 +29,17 @@ pub struct StructValue {
type BuiltinFunction = fn(Vec<Value>) -> Value;
#[derive(Debug, Clone)]
pub enum Function {
pub enum FunctionRef {
User(ast::Function),
Builtin(BuiltinFunction),
}
#[derive(Debug, Clone)]
pub struct Function {
pub partial: Vec<Value>,
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)) => {
Value::Function(function) => {
match &function.ref_ {
FunctionRef::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());
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));
}
Value::Function(Function::Builtin(builtin_function)) => {
return ExpressionResult::Value(builtin_function(argument_values));
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));
}
}
}
_ => panic!("type error: function call source must be a function"),
}
@@ -414,8 +440,42 @@ impl TreeWalkInterpreter {
match &source {
Value::Struct(struct_) => {
let s = struct_.lock().unwrap();
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");
}