ran into another type inference problem
This commit is contained in:
@@ -124,6 +124,7 @@ pub enum Expression {
|
||||
Reference(Location, String),
|
||||
Cast(Location, String, Box<Expression>),
|
||||
Primitive(Location, String, Vec<Expression>),
|
||||
Call(Location, Box<Expression>, Vec<Expression>),
|
||||
Block(Location, Vec<Statement>),
|
||||
}
|
||||
|
||||
@@ -146,6 +147,10 @@ impl PartialEq for Expression {
|
||||
Expression::Primitive(_, prim2, args2) => prim1 == prim2 && args1 == args2,
|
||||
_ => false,
|
||||
},
|
||||
Expression::Call(_, f1, a1) => match other {
|
||||
Expression::Call(_, f2, a2) => f1 == f2 && a1 == a2,
|
||||
_ => false,
|
||||
},
|
||||
Expression::Block(_, stmts1) => match other {
|
||||
Expression::Block(_, stmts2) => stmts1 == stmts2,
|
||||
_ => false,
|
||||
@@ -162,6 +167,7 @@ impl Expression {
|
||||
Expression::Reference(loc, _) => loc,
|
||||
Expression::Cast(loc, _, _) => loc,
|
||||
Expression::Primitive(loc, _, _) => loc,
|
||||
Expression::Call(loc, _, _) => loc,
|
||||
Expression::Block(loc, _) => loc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,33 @@ impl Expression {
|
||||
Ok(Value::calculate(op, arg_values)?)
|
||||
}
|
||||
|
||||
Expression::Call(loc, fun, args) => {
|
||||
let function = fun.eval(stdout, env)?;
|
||||
|
||||
match function {
|
||||
Value::Closure(name, mut closure_env, arguments, body) => {
|
||||
if args.len() != arguments.len() {
|
||||
return Err(EvalError::WrongArgCount(
|
||||
loc.clone(),
|
||||
name,
|
||||
arguments.len(),
|
||||
args.len(),
|
||||
));
|
||||
}
|
||||
|
||||
closure_env.new_scope();
|
||||
for (name, value) in arguments.into_iter().zip(args.iter()) {
|
||||
let value = value.eval(stdout, env)?;
|
||||
closure_env.insert(name, value);
|
||||
}
|
||||
let result = body.eval(stdout, &mut closure_env)?;
|
||||
closure_env.release_scope();
|
||||
Ok(result)
|
||||
}
|
||||
_ => Err(EvalError::NotAFunction(loc.clone(), function)),
|
||||
}
|
||||
}
|
||||
|
||||
Expression::Block(_, stmts) => {
|
||||
let mut result = Value::Void;
|
||||
|
||||
|
||||
@@ -205,9 +205,24 @@ UnaryExpression: Expression = {
|
||||
Expression::Primitive(Location::new(file_idx, l..le), "-".to_string(), vec![e]),
|
||||
<l: @L> "<" <v:"<var>"> ">" <e:UnaryExpression> <le: @L> =>
|
||||
Expression::Cast(Location::new(file_idx, l..le), v.to_string(), Box::new(e)),
|
||||
CallExpression,
|
||||
}
|
||||
|
||||
CallExpression: Expression = {
|
||||
<s: @L> <f:CallExpression> "(" <args: CallArguments> ")" <e: @L> =>
|
||||
Expression::Call(Location::new(file_idx, s..e), Box::new(f), args),
|
||||
AtomicExpression,
|
||||
}
|
||||
|
||||
CallArguments: Vec<Expression> = {
|
||||
=> vec![],
|
||||
<e:Expression> => vec![e],
|
||||
<mut args:CallArguments> "," <e:Expression> => {
|
||||
args.push(e);
|
||||
args
|
||||
}
|
||||
}
|
||||
|
||||
// finally, we describe our lowest-level expressions as "atomic", because
|
||||
// they cannot be further divided into parts
|
||||
AtomicExpression: Expression = {
|
||||
|
||||
@@ -105,6 +105,11 @@ where
|
||||
let comma_sepped_args = allocator.intersperse(args, CommaSep {});
|
||||
call.append(comma_sepped_args.parens())
|
||||
}
|
||||
Expression::Call(_, fun, args) => {
|
||||
let args = args.iter().map(|x| x.pretty(allocator));
|
||||
let comma_sepped_args = allocator.intersperse(args, CommaSep {});
|
||||
fun.pretty(allocator).append(comma_sepped_args.parens())
|
||||
}
|
||||
Expression::Block(_, stmts) => match stmts.split_last() {
|
||||
None => allocator.text("()"),
|
||||
Some((last, &[])) => last.pretty(allocator),
|
||||
@@ -167,7 +172,7 @@ fn type_suffix(x: &Option<ConstantType>) -> &'static str {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct CommaSep {}
|
||||
pub struct CommaSep {}
|
||||
|
||||
impl<'a, D, A> Pretty<'a, D, A> for CommaSep
|
||||
where
|
||||
|
||||
@@ -212,6 +212,17 @@ impl Expression {
|
||||
|
||||
(errors, warnings)
|
||||
}
|
||||
Expression::Call(_, func, args) => {
|
||||
let (mut errors, mut warnings) = func.validate(variable_map);
|
||||
|
||||
for arg in args.iter() {
|
||||
let (mut e, mut w) = arg.validate(variable_map);
|
||||
errors.append(&mut e);
|
||||
warnings.append(&mut w);
|
||||
}
|
||||
|
||||
(errors, warnings)
|
||||
}
|
||||
Expression::Block(_, stmts) => {
|
||||
let mut errors = vec![];
|
||||
let mut warnings = vec![];
|
||||
|
||||
Reference in New Issue
Block a user