ran into another type inference problem

This commit is contained in:
2024-02-05 17:30:16 -06:00
parent 7def938781
commit 9d41cf0da7
17 changed files with 267 additions and 24 deletions

View File

@@ -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,
}
}

View File

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

View File

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

View File

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

View File

@@ -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![];