checkpoint

This commit is contained in:
2024-04-22 20:49:44 -07:00
parent c8d6719eb7
commit 52d5c9252b
15 changed files with 1528 additions and 1358 deletions

View File

@@ -27,12 +27,6 @@ pub struct Program {
#[derive(Clone, Debug, PartialEq)]
pub enum TopLevel {
Expression(Expression),
Function(
Option<Name>,
Vec<(Name, Option<Type>)>,
Option<Type>,
Expression,
),
Structure(Location, Name, Vec<(Name, Type)>),
}
@@ -103,6 +97,13 @@ pub enum Expression {
Call(Location, Box<Expression>, Vec<Expression>),
Block(Location, Vec<Expression>),
Binding(Location, Name, Box<Expression>),
Function(
Location,
Option<Name>,
Vec<(Name, Option<Type>)>,
Option<Type>,
Box<Expression>,
),
}
impl Expression {
@@ -157,6 +158,12 @@ impl PartialEq for Expression {
Expression::Binding(_, name2, expr2) => name1 == name2 && expr1 == expr2,
_ => false,
},
Expression::Function(_, mname1, args1, mret1, body1) => match other {
Expression::Function(_, mname2, args2, mret2, body2) => {
mname1 == mname2 && args1 == args2 && mret1 == mret2 && body1 == body2
}
_ => false,
},
}
}
}
@@ -174,6 +181,7 @@ impl Expression {
Expression::Call(loc, _, _) => loc,
Expression::Block(loc, _) => loc,
Expression::Binding(loc, _, _) => loc,
Expression::Function(loc, _, _, _, _) => loc,
}
}
}

View File

@@ -24,22 +24,6 @@ impl Program {
for stmt in self.items.iter() {
match stmt {
TopLevel::Function(name, arg_names, _, body) => {
last_result = Value::Closure(
name.clone().map(Name::intern),
env.clone(),
arg_names
.iter()
.cloned()
.map(|(x, _)| Name::intern(x))
.collect(),
body.clone(),
);
if let Some(name) = name {
env.insert(name.clone().intern(), last_result.clone());
}
}
TopLevel::Expression(expr) => last_result = expr.eval(&mut stdout, &mut env)?,
TopLevel::Structure(_, _, _) => {
@@ -191,6 +175,25 @@ impl Expression {
env.insert(name.clone().intern(), actual_value.clone());
Ok(actual_value)
}
Expression::Function(_, name, arg_names, _, body) => {
let result = Value::Closure(
name.clone().map(Name::intern),
env.clone(),
arg_names
.iter()
.cloned()
.map(|(x, _)| Name::intern(x))
.collect(),
*body.clone(),
);
if let Some(name) = name {
env.insert(name.clone().intern(), result.clone());
}
Ok(result)
}
}
}
}

View File

@@ -79,16 +79,10 @@ ProgramTopLevel: Vec<TopLevel> = {
}
pub TopLevel: TopLevel = {
<f:Function> => f,
<s:Structure> => s,
<s:Expression> ";" => TopLevel::Expression(s),
}
Function: TopLevel = {
"function" <opt_name:Name?> "(" <args:Comma<Argument>> ")" <ret:("->" Type)?> <exp:Expression> ";" =>
TopLevel::Function(opt_name, args, ret.map(|x| x.1), exp),
}
Argument: (Name, Option<Type>) = {
<name_start: @L> <v:"<var>"> <name_end: @L> <t:(":" Type)?> =>
(Name::new(v, Location::new(file_idx, name_start..name_end)), t.map(|v| v.1)),
@@ -170,6 +164,13 @@ BindingExpression: Expression = {
Box::new(e),
),
FunctionExpression,
}
FunctionExpression: Expression = {
<s:@L> "function" <opt_name:Name?> "(" <args:Comma<Argument>> ")" <ret:("->" Type)?> <exp:Expression> <e:@L> =>
Expression::Function(Location::new(file_idx, s..e), opt_name, args, ret.map(|x| x.1), Box::new(exp)),
PrintExpression,
}

View File

@@ -21,47 +21,6 @@ impl TopLevel {
pub fn pretty<'a>(&self, allocator: &'a Allocator<'a>) -> DocBuilder<'a, Allocator<'a>> {
match self {
TopLevel::Expression(expr) => expr.pretty(allocator),
TopLevel::Function(name, args, rettype, body) => allocator
.text("function")
.append(allocator.space())
.append(
name.as_ref()
.map(|x| allocator.text(x.to_string()))
.unwrap_or_else(|| allocator.nil()),
)
.append(
allocator
.intersperse(
args.iter().map(|(x, t)| {
allocator.text(x.to_string()).append(
t.as_ref()
.map(|t| {
allocator
.text(":")
.append(allocator.space())
.append(t.pretty(allocator))
})
.unwrap_or_else(|| allocator.nil()),
)
}),
allocator.text(","),
)
.parens(),
)
.append(
rettype
.as_ref()
.map(|rettype| {
allocator
.space()
.append(allocator.text("->"))
.append(allocator.space())
.append(rettype.pretty(allocator))
})
.unwrap_or_else(|| allocator.nil()),
)
.append(allocator.space())
.append(body.pretty(allocator)),
TopLevel::Structure(_, name, fields) => allocator
.text("struct")
.append(allocator.space())
@@ -148,6 +107,47 @@ impl Expression {
.append(allocator.text("="))
.append(allocator.space())
.append(expr.pretty(allocator)),
Expression::Function(_, name, args, rettype, body) => allocator
.text("function")
.append(allocator.space())
.append(
name.as_ref()
.map(|x| allocator.text(x.to_string()))
.unwrap_or_else(|| allocator.nil()),
)
.append(
allocator
.intersperse(
args.iter().map(|(x, t)| {
allocator.text(x.to_string()).append(
t.as_ref()
.map(|t| {
allocator
.text(":")
.append(allocator.space())
.append(t.pretty(allocator))
})
.unwrap_or_else(|| allocator.nil()),
)
}),
allocator.text(","),
)
.parens(),
)
.append(
rettype
.as_ref()
.map(|rettype| {
allocator
.space()
.append(allocator.text("->"))
.append(allocator.space())
.append(rettype.pretty(allocator))
})
.unwrap_or_else(|| allocator.nil()),
)
.append(allocator.space())
.append(body.pretty(allocator)),
}
}
}

View File

@@ -84,9 +84,6 @@ impl Program {
let mut warnings = vec![];
for stmt in self.items.iter() {
if let TopLevel::Function(Some(name), _, _, _) = stmt {
bound_variables.insert(name.to_string(), name.location.clone());
}
let (mut new_errors, mut new_warnings) = stmt.validate_with_bindings(bound_variables);
errors.append(&mut new_errors);
warnings.append(&mut new_warnings);
@@ -119,18 +116,6 @@ impl TopLevel {
bound_variables: &mut ScopedMap<String, Location>,
) -> (Vec<Error>, Vec<Warning>) {
match self {
TopLevel::Function(name, arguments, _, body) => {
bound_variables.new_scope();
if let Some(name) = name {
bound_variables.insert(name.name.clone(), name.location.clone());
}
for (arg, _) in arguments.iter() {
bound_variables.insert(arg.name.clone(), arg.location.clone());
}
let result = body.validate(bound_variables);
bound_variables.release_scope();
result
}
TopLevel::Expression(expr) => expr.validate(bound_variables),
TopLevel::Structure(_, _, _) => (vec![], vec![]),
}
@@ -214,6 +199,18 @@ impl Expression {
(errors, warnings)
}
Expression::Function(_, name, arguments, _, body) => {
if let Some(name) = name {
variable_map.insert(name.name.clone(), name.location.clone());
}
variable_map.new_scope();
for (arg, _) in arguments.iter() {
variable_map.insert(arg.name.clone(), arg.location.clone());
}
let result = body.validate(variable_map);
variable_map.release_scope();
result
}
}
}
}