added interpereter support for traits
This commit is contained in:
@@ -28,11 +28,6 @@ fn unit_function() {
|
|||||||
let a: i64 = 4;
|
let a: i64 = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main(): i64 {
|
|
||||||
add(4, subtract(5, 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn returns_user(): User {
|
fn returns_user(): User {
|
||||||
return User{
|
return User{
|
||||||
id: 4,
|
id: 4,
|
||||||
@@ -74,11 +69,9 @@ fn if_expression(): i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main(): i64 {
|
fn main(): i64 {
|
||||||
if (false) {
|
let a = User{id: 4};
|
||||||
add(4, 4)
|
let b = a.instance_method();
|
||||||
} else {
|
b
|
||||||
61
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestTrait trait {
|
type TestTrait trait {
|
||||||
|
|||||||
@@ -29,11 +29,17 @@ pub struct StructValue {
|
|||||||
type BuiltinFunction = fn(Vec<Value>) -> Value;
|
type BuiltinFunction = fn(Vec<Value>) -> Value;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Function {
|
pub enum FunctionRef {
|
||||||
User(ast::Function),
|
User(ast::Function),
|
||||||
Builtin(BuiltinFunction),
|
Builtin(BuiltinFunction),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Function {
|
||||||
|
pub partial: Vec<Value>,
|
||||||
|
pub ref_: FunctionRef,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Numeric(NumericValue),
|
Numeric(NumericValue),
|
||||||
@@ -89,7 +95,12 @@ impl Context {
|
|||||||
ast::ModuleItem::Function(function) => {
|
ast::ModuleItem::Function(function) => {
|
||||||
ctx.environment.insert(
|
ctx.environment.insert(
|
||||||
function.declaration.name.name.value.to_string(),
|
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_) => {
|
ast::ModuleItem::Impl(impl_) => {
|
||||||
@@ -214,7 +225,12 @@ impl TreeWalkInterpreter {
|
|||||||
let mut ctx = Context::from_module(module);
|
let mut ctx = Context::from_module(module);
|
||||||
|
|
||||||
let main = match &ctx.environment["main"] {
|
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"),
|
_ => panic!("main should be a user defined function"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -362,15 +378,25 @@ impl TreeWalkInterpreter {
|
|||||||
argument_values.push(argument_value);
|
argument_values.push(argument_value);
|
||||||
}
|
}
|
||||||
match &source {
|
match &source {
|
||||||
Value::Function(Function::User(user_function)) => {
|
Value::Function(function) => {
|
||||||
let mut fn_ctx = ctx.new_env();
|
match &function.ref_ {
|
||||||
for (i, function_arg) in user_function.declaration.arguments.iter().enumerate() {
|
FunctionRef::User(user_function) => {
|
||||||
fn_ctx.set_variable(function_arg.name.name.value.to_string(), &argument_values[i].clone());
|
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"),
|
_ => panic!("type error: function call source must be a function"),
|
||||||
}
|
}
|
||||||
@@ -414,7 +440,41 @@ impl TreeWalkInterpreter {
|
|||||||
match &source {
|
match &source {
|
||||||
Value::Struct(struct_) => {
|
Value::Struct(struct_) => {
|
||||||
let s = struct_.lock().unwrap();
|
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");
|
panic!("TypeError: struct getter used with non-struct");
|
||||||
|
|||||||
Reference in New Issue
Block a user