WIP evaluating self in method call
This commit is contained in:
parent
b5ec8116a2
commit
d913443e97
@ -127,7 +127,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
use crate::ast::ExpressionKind::*;
|
use crate::ast::ExpressionKind::*;
|
||||||
|
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
SelfValue => panic!(),
|
SelfValue => Expression::Lookup(Lookup::SelfParam),
|
||||||
NatLiteral(n) => Expression::Literal(Literal::Nat(*n)),
|
NatLiteral(n) => Expression::Literal(Literal::Nat(*n)),
|
||||||
FloatLiteral(f) => Expression::Literal(Literal::Float(*f)),
|
FloatLiteral(f) => Expression::Literal(Literal::Float(*f)),
|
||||||
//TODO implement handling string literal prefixes
|
//TODO implement handling string literal prefixes
|
||||||
@ -136,10 +136,19 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
BinExp(binop, lhs, rhs) => self.binop(binop, lhs, rhs),
|
||||||
PrefixExp(op, arg) => self.prefix(op, arg),
|
PrefixExp(op, arg) => self.prefix(op, arg),
|
||||||
Value(qualified_name) => self.value(qualified_name),
|
Value(qualified_name) => self.value(qualified_name),
|
||||||
Call { f, arguments } => Expression::Call {
|
Call { f, arguments } => {
|
||||||
f: Box::new(self.expression(f)),
|
let f = self.expression(f);
|
||||||
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
|
||||||
|
//correctly
|
||||||
|
if let Expression::Access { name, expr } = f {
|
||||||
|
let def_id = unimplemented!();
|
||||||
|
let method = Expression::Lookup(Lookup::Function(def_id));
|
||||||
|
Expression::CallMethod { f: Box::new(method), args, self_expr: expr }
|
||||||
|
} else {
|
||||||
|
Expression::Call { f: Box::new(f), args }
|
||||||
|
}
|
||||||
|
}
|
||||||
TupleLiteral(exprs) => Expression::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
TupleLiteral(exprs) => Expression::Tuple(exprs.iter().map(|e| self.expression(e)).collect()),
|
||||||
IfExpression { discriminator, body } =>
|
IfExpression { discriminator, body } =>
|
||||||
self.reduce_if_expression(discriminator.as_ref().map(|x| x.as_ref()), body),
|
self.reduce_if_expression(discriminator.as_ref().map(|x| x.as_ref()), body),
|
||||||
|
@ -57,6 +57,7 @@ pub enum Expression {
|
|||||||
Access { name: String, expr: Box<Expression> },
|
Access { name: String, expr: Box<Expression> },
|
||||||
Callable(Callable),
|
Callable(Callable),
|
||||||
Call { f: Box<Expression>, args: Vec<Expression> },
|
Call { f: Box<Expression>, args: Vec<Expression> },
|
||||||
|
CallMethod { f: Box<Expression>, args: Vec<Expression>, self_expr: Box<Expression> },
|
||||||
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },
|
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },
|
||||||
CaseMatch { cond: Box<Expression>, alternatives: Vec<Alternative> },
|
CaseMatch { cond: Box<Expression>, alternatives: Vec<Alternative> },
|
||||||
Loop { cond: Box<Expression>, statements: Vec<Statement> },
|
Loop { cond: Box<Expression>, statements: Vec<Statement> },
|
||||||
@ -90,6 +91,7 @@ pub enum Lookup {
|
|||||||
GlobalVar(DefId),
|
GlobalVar(DefId),
|
||||||
Function(DefId),
|
Function(DefId),
|
||||||
Param(u8),
|
Param(u8),
|
||||||
|
SelfParam,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -133,6 +133,13 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
e => return Err(format!("Param lookup error, got {:?}", e).into()),
|
e => return Err(format!("Param lookup error, got {:?}", e).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Lookup::SelfParam => {
|
||||||
|
let mem = Memory::self_param();
|
||||||
|
match self.state.environments.lookup(&mem) {
|
||||||
|
Some(MemoryValue::Primitive(prim)) => prim.clone(),
|
||||||
|
e => return Err(format!("SelfParam lookup error, got {:?}", e).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
Lookup::LocalVar(ref id) | Lookup::GlobalVar(ref id) => {
|
Lookup::LocalVar(ref id) | Lookup::GlobalVar(ref id) => {
|
||||||
let mem = id.into();
|
let mem = id.into();
|
||||||
match self.state.environments.lookup(&mem) {
|
match self.state.environments.lookup(&mem) {
|
||||||
@ -151,7 +158,9 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
self.state.environments.insert(mem, MemoryValue::Primitive(evaluated));
|
self.state.environments.insert(mem, MemoryValue::Primitive(evaluated));
|
||||||
Primitive::unit()
|
Primitive::unit()
|
||||||
}
|
}
|
||||||
Expression::Call { box f, args } => self.call_expression(f, args)?,
|
Expression::Call { box f, args } => self.call_expression(f, args, None)?,
|
||||||
|
Expression::CallMethod { box f, args, box self_expr } =>
|
||||||
|
self.call_expression(f, args, Some(self_expr))?,
|
||||||
Expression::Callable(Callable::DataConstructor { type_id, tag }) => {
|
Expression::Callable(Callable::DataConstructor { type_id, tag }) => {
|
||||||
let arity = self.type_context.lookup_variant_arity(&type_id, tag).unwrap();
|
let arity = self.type_context.lookup_variant_arity(&type_id, tag).unwrap();
|
||||||
if arity == 0 {
|
if arity == 0 {
|
||||||
@ -314,7 +323,13 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
Err("No valid match in match expression".into())
|
Err("No valid match in match expression".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_expression(&mut self, f: Expression, args: Vec<Expression>) -> EvalResult<Primitive> {
|
//TODO need to do something with self_expr to make method invocations actually work
|
||||||
|
fn call_expression(
|
||||||
|
&mut self,
|
||||||
|
f: Expression,
|
||||||
|
args: Vec<Expression>,
|
||||||
|
self_expr: Option<Expression>,
|
||||||
|
) -> EvalResult<Primitive> {
|
||||||
let func = match self.expression(f)? {
|
let func = match self.expression(f)? {
|
||||||
Primitive::Callable(func) => func,
|
Primitive::Callable(func) => func,
|
||||||
other => return Err(format!("Trying to call non-function value: {:?}", other).into()),
|
other => return Err(format!("Trying to call non-function value: {:?}", other).into()),
|
||||||
@ -326,7 +341,7 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
match self.state.environments.lookup(&mem) {
|
match self.state.environments.lookup(&mem) {
|
||||||
Some(MemoryValue::Function(FunctionDefinition { body })) => {
|
Some(MemoryValue::Function(FunctionDefinition { body })) => {
|
||||||
let body = body.clone(); //TODO ideally this clone would not happen
|
let body = body.clone(); //TODO ideally this clone would not happen
|
||||||
self.apply_function(body, args)
|
self.apply_function(body, args, self_expr)
|
||||||
}
|
}
|
||||||
e => Err(format!("Error looking up function with id {}: {:?}", def_id, e).into()),
|
e => Err(format!("Error looking up function with id {}: {:?}", def_id, e).into()),
|
||||||
}
|
}
|
||||||
@ -340,7 +355,7 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
)
|
)
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
self.apply_function(body, args)
|
self.apply_function(body, args, None)
|
||||||
}
|
}
|
||||||
Callable::DataConstructor { type_id, tag } => {
|
Callable::DataConstructor { type_id, tag } => {
|
||||||
let arity = self.type_context.lookup_variant_arity(&type_id, tag).unwrap();
|
let arity = self.type_context.lookup_variant_arity(&type_id, tag).unwrap();
|
||||||
@ -469,7 +484,13 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_function(&mut self, body: Vec<Statement>, args: Vec<Expression>) -> EvalResult<Primitive> {
|
fn apply_function(
|
||||||
|
&mut self,
|
||||||
|
body: Vec<Statement>,
|
||||||
|
args: Vec<Expression>,
|
||||||
|
self_expr: Option<Expression>,
|
||||||
|
) -> EvalResult<Primitive> {
|
||||||
|
let self_expr = if let Some(expr) = self_expr { Some(self.expression(expr)?) } else { None };
|
||||||
let mut evaluated_args: Vec<Primitive> = vec![];
|
let mut evaluated_args: Vec<Primitive> = vec![];
|
||||||
for arg in args.into_iter() {
|
for arg in args.into_iter() {
|
||||||
evaluated_args.push(self.expression(arg)?);
|
evaluated_args.push(self.expression(arg)?);
|
||||||
@ -478,12 +499,15 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
let mut frame_state = State { environments: self.state.environments.new_scope(None) };
|
let mut frame_state = State { environments: self.state.environments.new_scope(None) };
|
||||||
let mut evaluator = Evaluator::new(&mut frame_state, self.type_context);
|
let mut evaluator = Evaluator::new(&mut frame_state, self.type_context);
|
||||||
|
|
||||||
|
if let Some(evaled) = self_expr {
|
||||||
|
let mem = Memory::self_param();
|
||||||
|
evaluator.state.environments.insert(mem, MemoryValue::Primitive(evaled));
|
||||||
|
}
|
||||||
for (n, evaled) in evaluated_args.into_iter().enumerate() {
|
for (n, evaled) in evaluated_args.into_iter().enumerate() {
|
||||||
let n = n as u8;
|
let n = n as u8;
|
||||||
let mem = n.into();
|
let mem = n.into();
|
||||||
evaluator.state.environments.insert(mem, MemoryValue::Primitive(evaled));
|
evaluator.state.environments.insert(mem, MemoryValue::Primitive(evaled));
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluator.block(body)
|
evaluator.block(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,12 @@ enum Memory {
|
|||||||
Index(u32),
|
Index(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Memory {
|
||||||
|
fn self_param() -> Self {
|
||||||
|
Memory::Index(3_999_999)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This is for function param lookups, and is a hack
|
// This is for function param lookups, and is a hack
|
||||||
impl From<u8> for Memory {
|
impl From<u8> for Memory {
|
||||||
fn from(n: u8) -> Self {
|
fn from(n: u8) -> Self {
|
||||||
|
Loading…
Reference in New Issue
Block a user