summaryrefslogtreecommitdiffstats
path: root/crates
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-28 00:20:59 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-28 10:06:19 +0200
commitf70b2b4c6c96b315c69f5de65eb7194062980bd0 (patch)
tree454ef4fa94ab5fa4a0ad950b880736b9d74eb3bb /crates
parente9a91ade7eed42f576905facd9acdbe14a3cbac2 (diff)
downloadrebel-f70b2b4c6c96b315c69f5de65eb7194062980bd0.tar
rebel-f70b2b4c6c96b315c69f5de65eb7194062980bd0.zip
rebel-lang: implement simple assignments for REPL
Diffstat (limited to 'crates')
-rw-r--r--crates/rebel-lang/examples/repl.rs33
-rw-r--r--crates/rebel-lang/src/scope.rs40
2 files changed, 63 insertions, 10 deletions
diff --git a/crates/rebel-lang/examples/repl.rs b/crates/rebel-lang/examples/repl.rs
index 0e3debc..07c906f 100644
--- a/crates/rebel-lang/examples/repl.rs
+++ b/crates/rebel-lang/examples/repl.rs
@@ -51,6 +51,7 @@ fn main() -> rustyline::Result<()> {
while let Ok(line) = rl.readline("> ") {
rl.add_history_entry(line.as_str())?;
+
let tokens = match tokenize::token_stream(&line) {
Ok(value) => value,
Err(err) => {
@@ -58,21 +59,37 @@ fn main() -> rustyline::Result<()> {
continue;
}
};
- let expr = match recipe::expr(&tokens) {
+ let stmt = match recipe::body_stmt(&tokens) {
Ok(value) => value,
Err(err) => {
println!("Parse error: {err}");
continue;
}
};
- match Type::ast_expr_type(&ctx, &expr) {
- Ok(_) => (),
- Err(err) => {
- println!("Type error: {err:?}");
- continue;
+
+ match &stmt {
+ rebel_parse::ast::BodyStmt::Assign { dest: _, expr } => {
+ match Type::ast_expr_type(&ctx, expr) {
+ Ok(_) => (),
+ Err(err) => {
+ println!("Type error: {err:?}");
+ continue;
+ }
+ };
}
- };
- let value = match Value::eval(&ctx, &expr) {
+ rebel_parse::ast::BodyStmt::Expr { expr } => {
+ match Type::ast_expr_type(&ctx, expr) {
+ Ok(_) => (),
+ Err(err) => {
+ println!("Type error: {err:?}");
+ continue;
+ }
+ };
+ }
+ rebel_parse::ast::BodyStmt::Empty => {}
+ }
+
+ let value = match ctx.run(&stmt) {
Ok(value) => value,
Err(err) => {
println!("Eval error: {err:?}");
diff --git a/crates/rebel-lang/src/scope.rs b/crates/rebel-lang/src/scope.rs
index bae9678..1d574b3 100644
--- a/crates/rebel-lang/src/scope.rs
+++ b/crates/rebel-lang/src/scope.rs
@@ -5,7 +5,7 @@ use rebel_parse::ast;
use crate::{
func::Func,
typing::{Type, TypeFamily},
- value::Value,
+ value::{self, EvalError, Value},
};
#[derive(Debug, Default)]
@@ -14,8 +14,44 @@ pub struct Context {
pub methods: HashMap<TypeFamily, HashMap<&'static str, Func>>,
}
+impl Context {
+ pub fn run(&mut self, stmt: &ast::BodyStmt) -> value::Result<Value> {
+ match stmt {
+ ast::BodyStmt::Assign { dest, expr } => {
+ let value = Value::eval(self, expr)?;
+ let typ = value.typ().or(Err(EvalError))?;
+
+ // TODO: Handle specified type
+ let ast::TypedExpr {
+ expr: dest_expr,
+ typ: _,
+ } = dest;
+
+ // TODO: Handle other assignable expressions
+ let dest_path = match dest_expr {
+ ast::Expr::Path(path) => path,
+ _ => return Err(EvalError),
+ };
+ let [dest_ident] = dest_path.components[..] else {
+ return Err(EvalError);
+ };
+
+ // TODO: Lexical scoping
+ self.values.0.insert(
+ dest_ident.name.to_owned(),
+ ModuleEntry::Def((typ, (Some(value.clone())))),
+ );
+
+ Ok(value)
+ }
+ ast::BodyStmt::Expr { expr } => Value::eval(self, expr),
+ ast::BodyStmt::Empty => Ok(Value::Unit),
+ }
+ }
+}
+
#[derive(Debug, Default)]
-pub struct Module(HashMap<String, ModuleEntry>);
+pub struct Module(pub HashMap<String, ModuleEntry>);
impl Module {
pub fn lookup(&self, path: &[ast::Ident<'_>]) -> Option<(&Type, Option<&Value>)> {