diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-01 00:06:46 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-01 00:06:46 +0200 |
commit | 802884a04625b940a45aeb7cbeb504ff2c18a9ff (patch) | |
tree | 1b68c243d0e1af3cc1f01641bfa8401540ec5198 | |
parent | 3d9d7fd594323d04f77c48ddc3ef2c2b6dc580b7 (diff) | |
download | rebel-802884a04625b940a45aeb7cbeb504ff2c18a9ff.tar rebel-802884a04625b940a45aeb7cbeb504ff2c18a9ff.zip |
rebel-lang: scope: add helpers for path handling
-rw-r--r-- | crates/rebel-lang/src/scope.rs | 39 | ||||
-rw-r--r-- | crates/rebel-lang/src/typing.rs | 17 | ||||
-rw-r--r-- | crates/rebel-lang/src/value.rs | 7 |
3 files changed, 30 insertions, 33 deletions
diff --git a/crates/rebel-lang/src/scope.rs b/crates/rebel-lang/src/scope.rs index 64fe505..ccf2064 100644 --- a/crates/rebel-lang/src/scope.rs +++ b/crates/rebel-lang/src/scope.rs @@ -42,15 +42,36 @@ impl Default for Context { } impl Context { + pub fn local_ident<'a>(path: &'a ast::Path) -> Option<ast::Ident<'a>> { + let [ident] = path.components[..] else { + return None; + }; + Some(ident) + } + + pub fn lookup_var(&self, path: &ast::Path) -> Option<&Var> { + if path.components == [ast::Ident { name: "_" }] { + return None; + } + + self.vars.lookup(&path.components) + } + + pub fn lookup_type(&self, path: &ast::Path) -> Option<&Type> { + if path.components == [ast::Ident { name: "_" }] { + return Some(&Type::Free); + } + + self.types.lookup(&path.components) + } + pub fn record_type(&mut self, stmt: &ast::BlockStmt) -> typing::Result<Type> { match stmt { ast::BlockStmt::Let { dest, expr } => { let ast::TypedPat { pat, typ } = dest.as_ref(); let pat::Pat::Path(dest_path) = pat; - let [dest_ident] = dest_path.components[..] else { - return Err(TypeError); - }; + let dest_ident = Context::local_ident(dest_path).ok_or(TypeError)?; let explicit_type = if let Some(typ) = typ { Type::ast_type(self, typ)? @@ -80,9 +101,7 @@ impl Context { } ast::BlockStmt::Assign { dest, expr } => { let pat::Pat::Path(dest_path) = dest.as_ref(); - let [dest_ident] = dest_path.components[..] else { - return Err(TypeError); - }; + let dest_ident = Context::local_ident(dest_path).ok_or(TypeError)?; let expr_type = Type::ast_expr_type(self, expr)?; @@ -114,9 +133,7 @@ impl Context { let ast::TypedPat { pat, typ } = dest.as_ref(); let pat::Pat::Path(dest_path) = pat; - let [dest_ident] = dest_path.components[..] else { - unreachable!("Type error during eval"); - }; + let dest_ident = Context::local_ident(dest_path).expect("Type error during eval"); let explicit_type = if let Some(typ) = typ { Type::ast_type(self, typ).expect("Type error during eval") @@ -152,9 +169,7 @@ impl Context { } ast::BlockStmt::Assign { dest, expr } => { let pat::Pat::Path(dest_path) = dest.as_ref(); - let [dest_ident] = dest_path.components[..] else { - unreachable!("Type error during eval"); - }; + let dest_ident = Context::local_ident(dest_path).expect("Type error during eval"); let value = Value::eval(self, expr)?; let expr_type = value.typ().or(Err(EvalError))?; diff --git a/crates/rebel-lang/src/typing.rs b/crates/rebel-lang/src/typing.rs index 5eb781e..3fd0ee2 100644 --- a/crates/rebel-lang/src/typing.rs +++ b/crates/rebel-lang/src/typing.rs @@ -90,13 +90,7 @@ impl Type { } fn path_type(ctx: &Context, path: &ast::Path<'_>) -> Result<Type> { - use Type::*; - - if path.components == [ast::Ident { name: "_" }] { - return Ok(Free); - } - - ctx.types.lookup(&path.components).cloned().ok_or(TypeError) + ctx.lookup_type(path).cloned().ok_or(TypeError) } fn literal_type(ctx: &Context, lit: &typ::Literal<'_>) -> Result<Type> { @@ -298,14 +292,7 @@ impl Type { } fn path_expr_type(ctx: &Context, path: &ast::Path<'_>) -> Result<Type> { - if path.components == [ast::Ident { name: "_" }] { - return Err(TypeError); - } - - ctx.vars - .lookup(&path.components) - .map(|var| var.inferred_type.clone()) - .ok_or(TypeError) + Ok(ctx.lookup_var(path).ok_or(TypeError)?.inferred_type.clone()) } fn check_string_piece( diff --git a/crates/rebel-lang/src/value.rs b/crates/rebel-lang/src/value.rs index ab21d0b..0780377 100644 --- a/crates/rebel-lang/src/value.rs +++ b/crates/rebel-lang/src/value.rs @@ -245,12 +245,7 @@ impl Value { } fn eval_path(ctx: &Context, path: &ast::Path<'_>) -> Result<Value> { - if path.components == [ast::Ident { name: "_" }] { - return Err(EvalError); - } - - ctx.vars - .lookup(&path.components) + ctx.lookup_var(path) .and_then(|var| var.value.clone()) .ok_or(EvalError) } |