diff options
-rw-r--r-- | crates/rebel-lang/benches/recipe.rs | 14 | ||||
-rw-r--r-- | crates/rebel-lang/src/scope.rs | 62 | ||||
-rw-r--r-- | crates/rebel-lang/src/typing.rs | 6 | ||||
-rw-r--r-- | crates/rebel-lang/src/value.rs | 6 |
4 files changed, 45 insertions, 43 deletions
diff --git a/crates/rebel-lang/benches/recipe.rs b/crates/rebel-lang/benches/recipe.rs index 5b9a440..3eb8c1b 100644 --- a/crates/rebel-lang/benches/recipe.rs +++ b/crates/rebel-lang/benches/recipe.rs @@ -21,21 +21,11 @@ fn context() -> Context { ctx.vars.0.insert( "workdir".to_owned(), - ModuleEntry::Def(Var { - explicit_type: Type::Str, - inferred_type: Type::Str, - value: Value::Str("workdir".to_owned()), - initialized: true, - }), + ModuleEntry::Def(Var::new(Type::Str, Value::Str("workdir".to_owned())).unwrap()), ); ctx.vars.0.insert( "name".to_owned(), - ModuleEntry::Def(Var { - explicit_type: Type::Str, - inferred_type: Type::Str, - value: Value::Str("gpm".to_owned()), - initialized: true, - }), + ModuleEntry::Def(Var::new(Type::Str, Value::Str("gpm".to_owned())).unwrap()), ); ctx diff --git a/crates/rebel-lang/src/scope.rs b/crates/rebel-lang/src/scope.rs index f0fe443..08149a9 100644 --- a/crates/rebel-lang/src/scope.rs +++ b/crates/rebel-lang/src/scope.rs @@ -12,9 +12,43 @@ use crate::{ #[derive(Debug, Clone)] pub struct Var { pub explicit_type: Type, - pub inferred_type: Type, - pub value: Value, - pub initialized: bool, + inferred_type: Type, + value: Value, + initialized: bool, +} + +impl Var { + pub fn new(explicit_type: Type, value: Value) -> Result<Self> { + Ok(Var { + explicit_type: explicit_type.clone(), + inferred_type: explicit_type.unify(value.typ()?, Coerce::Assign)?, + value, + initialized: true, + }) + } + + pub fn new_uninitialized(explicit_type: Type) -> Self { + Var { + inferred_type: explicit_type.clone(), + explicit_type, + value: Value::Uninitialized, + initialized: false, + } + } + + pub fn inferred_type(&self) -> Result<&Type> { + if !self.initialized { + return Err(Error::typ("uninitialized variable")); + } + Ok(&self.inferred_type) + } + + pub fn value(&self) -> Result<&Value> { + if !self.initialized { + return Err(Error::typ("uninitialized variable")); + } + Ok(&self.value) + } } #[derive(Debug, Clone)] @@ -290,15 +324,8 @@ impl Context { return Ok(Type::Unit); } - self.vars.insert( - dest_ident.name, - Var { - inferred_type: explicit_type.clone(), - explicit_type, - value: Value::Uninitialized, - initialized: false, - }, - ); + self.vars + .insert(dest_ident.name, Var::new_uninitialized(explicit_type)); let Some(expr_type) = expr_type else { return Ok(Type::Unit); @@ -337,15 +364,8 @@ impl Context { return Ok(Value::Unit); } - self.vars.insert( - dest_ident.name, - Var { - inferred_type: explicit_type.clone(), - explicit_type, - value: Value::Uninitialized, - initialized: false, - }, - ); + self.vars + .insert(dest_ident.name, Var::new_uninitialized(explicit_type)); let Some(value) = value else { return Ok(Value::Unit); diff --git a/crates/rebel-lang/src/typing.rs b/crates/rebel-lang/src/typing.rs index 8edc36a..7dbb6df 100644 --- a/crates/rebel-lang/src/typing.rs +++ b/crates/rebel-lang/src/typing.rs @@ -296,11 +296,7 @@ impl Type { } fn path_expr_type(ctx: &Context, path: &ast::Path<'_>) -> Result<Type> { - let var = ctx.lookup_var(path)?; - if !var.initialized { - return Err(Error::typ("uninitialized variable")); - } - Ok(var.inferred_type.clone()) + Ok(ctx.lookup_var(path)?.inferred_type()?.clone()) } fn check_string_piece( diff --git a/crates/rebel-lang/src/value.rs b/crates/rebel-lang/src/value.rs index bb8556d..614002f 100644 --- a/crates/rebel-lang/src/value.rs +++ b/crates/rebel-lang/src/value.rs @@ -266,11 +266,7 @@ impl Value { } fn eval_path(ctx: &Context, path: &ast::Path<'_>) -> Result<Value> { - let var = ctx.lookup_var(path)?; - if !var.initialized { - return Err(Error::typ("uninitialized variable")); - } - Ok(var.value.clone()) + Ok(ctx.lookup_var(path)?.value()?.clone()) } fn eval_literal(ctx: &Context, lit: &expr::Literal<'_>) -> Result<Value> { |