From f70b2b4c6c96b315c69f5de65eb7194062980bd0 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 28 Apr 2024 00:20:59 +0200 Subject: rebel-lang: implement simple assignments for REPL --- crates/rebel-lang/examples/repl.rs | 33 +++++++++++++++++++++++-------- crates/rebel-lang/src/scope.rs | 40 ++++++++++++++++++++++++++++++++++++-- 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>, } +impl Context { + pub fn run(&mut self, stmt: &ast::BodyStmt) -> value::Result { + 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); +pub struct Module(pub HashMap); impl Module { pub fn lookup(&self, path: &[ast::Ident<'_>]) -> Option<(&Type, Option<&Value>)> { -- cgit v1.2.3