summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/rebel-lang/benches/recipe.rs14
-rw-r--r--crates/rebel-lang/src/scope.rs62
-rw-r--r--crates/rebel-lang/src/typing.rs6
-rw-r--r--crates/rebel-lang/src/value.rs6
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> {