checkpoint
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user