added interpereter support for traits
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)) => {
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user